HDU 5510(KMP+思惟)

 

傳送門php

題面:ios

Bazinga

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 6560    Accepted Submission(s): 2003

 c++

Problem Description算法

Ladies and gentlemen, please sit up straight.
Don't tilt your head. I'm serious.數組


For n given strings S1,S2,⋯,Sn, labelled from 1 to n, you should find the largest i (1≤in) such that there exists an integer j (1≤j<i) and Sj is not a substring of Si.

A substring of a string Si is another string that occurs in Si. For example, ``ruiz" is a substring of ``ruizhang", and ``rzhang" is not a substring of ``ruizhang".函數

 

 

Inputui

 

The first line contains an integer t (1≤t≤50) which is the number of test cases.
For each test case, the first line is the positive integer n (1≤n≤500) and in the following n lines list are the strings S1,S2,⋯,Sn.
All strings are given in lower-case letters and strings are no longer than 2000 letters.spa

 

 

Output指針

 

For each test case, output the largest label you get. If it does not exist, output −1.code

 

 

Sample Input

 

45ababczabcabcdzabcd4youlovinyouaboutlovinyouallaboutlovinyou5dedefabcdabcdeabcdef3abaccc

 

 

Sample Output

 

Case #1: 4Case #2: -1Case #3: 4Case #4: 3

 

    

    題目描述:每次給你n個字符串S,問你最大的i,使得字符串Sj(0<=j<i)全都不是Si的字串。

 

 

    題面分析:經過讀題,由於要求某個串是不是某個串的字串,所以能夠判斷出這是一道很經典的字符串匹配問題。

 

 

    從題目來看,這貌似就是一道很普通的多模匹配的問題,用AC自動機去解決,可是這題若是用AC自動機去作,先建樹再用每個字符串進行匹配的話會致使TLE。所以AC自動機在這個題目上並不適合。

    所以咱們得拓寬咱們的思惟。

 

 

    進一步分析咱們能夠發現,對於第j串字符串,假若前j串都是j的字串,那麼咱們下一步只須要判斷j是不是j+1的字串便可(由於若是j是j+1的字串,而前j串又是j的字串,易得j+1串也是前j串的字串,進而得出前j+1串是j+1串的字串。)

 

 

    而假若j串並非j+1串的字串,那麼下一步只需判斷j串是不是j+2串的字串便可。

    所以,這道題就被巧妙地轉化成了單模匹配的問題了。如此咱們就能夠經過KMP算法,使用相似指針的作法去用較短的時間匹配出答案。

    附上KMP算法的代碼:

#include <bits/stdc++.h>
#define maxn 1005
using namespace std;
namespace CHENJR{//此處運用了命名保護,防止next數組報錯

int next[maxn];
string str[maxn];
void get_next(string s){
    memset(next,0,sizeof(next));
    int len=s.length();
    int i,j;
    j=next[0]=-1;
    i=0;
    while(i<len){
        while(j!=-1&&s[i]!=s[j]) j=next[j];
        next[++i]=++j;
    }
}
bool kmp(string a,string b){
    int lena=a.length();
    int lenb=b.length();
    get_next(b);
    int i=0,j=0;
    while(i<lena){
        while(j!=-1&&a[i]!=b[j]) j=next[j];
        i++,j++;
        if(j>=lenb) return true;
    }
    return false;
}

void main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t;
    int cnt=0;
    while(t--){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>str[i];
        }
        int j=1;
        
        int ans=-1;
        for(int i=2;i<=n;i++){
            while(j<i&&kmp(str[i],str[j])){
                j++;
            }
            if(j<i) ans=i;
        }
        cout<<"Case #"<<++cnt<<": "<<ans<<endl;
    }
}

}
int main()
{
    CHENJR::main();
    exit(0);
}

 

    然而事實上,在頭文件string.h內是含有一個strstr()函數用來尋找字串的。(可是須要注意的是,strstr()這個函數在最壞的狀況下O(n^2)的複雜度,而kmp算法的複雜度是穩定在O(n)的。所以使用strstr()函數有風險,可是很省力省時間)對於這題,用strstr()函數是沒有任何問題的。對於這個函數就當小小的積累了吧。

    附上代碼:

#include <bits/stdc++.h>
#define maxn 2005
using namespace std;
char str[maxn][maxn];
int main()
{
    int t;
    int cnt=0;
    scanf("%d",&t);
    while(t--){
        memset(str,0,sizeof(str));
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",str[i]);
        }
        int ans=-1,j=1;
        for(int i=2;i<=n;i++){
            while(j<i&&strstr(str[i],str[j])){
                j++;
            }
            if(j<i) ans=i;
        }
        printf("Case #%d: %d\n",++cnt,ans);
    }
    return 0;
}
相關文章
相關標籤/搜索