傳送門php
題面:ios
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≤i≤n) 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; }