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".
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".
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.
4 5 ab abc zabc abcd zabcd 4 you lovinyou aboutlovinyou allaboutlovinyou 5 de def abcd abcde abcdef 3 a ba ccc
Case #1: 4 Case #2: -1 Case #3: 4 Case #4: 3
因为是找最大值所以从后往前找哪个不是他的子串,那么正常想法就是从第一个开始判断了,但是那样复杂度会过高。
所以对字符串进行预处理,如果第I个字符串和第i+1个匹配, 就把mark【i】置为1.
这样,对于一个字符串,当判断前面的字符串是不是他的子串时,可以先判断mark[j]是否为1,因为如果为一说明他是(j+1)的子串,就判断(j+1)与母串关系就好了。#include <iostream> #include<cstdio> #include<cstring> using namespace std; char s[505][2005]; int mark[505]; int n[505][2005]; void kmp(int i) { n[i][0]=-1; int k=-1; int j=0; int len=strlen(s[i]); while(j<len) { if(k==-1||s[i][j]==s[i][k]) { k++; j++; n[i][j]=k; } else k=n[i][k]; } } int match(char *a,char *b,int x) { int len1=strlen(a),len2=strlen(b); //kmp(len1); int flag=0; for(int i=0,j=0;i<len2;i++) { while(j>0&&a[j]!=b[i])j=n[x][j]; if(a[j]==b[i])j++; if(j==len1){flag++;break;} } if(flag) { return 1; } else return 0; } int main() { int n; int t; cin>>t; int z=1; while(t--) { scanf("%d",&n); memset(mark,0,sizeof(mark)); getchar(); for(int i=0;i<n;i++) { scanf("%s",s[i]); kmp(i); } int ans=0; for(int i=0;i<n-1;i++) { mark[i]=match(s[i],s[i+1],i); } int mmax=0; for(int i=n-1;i>=0;i--) { for(int j=0;j<i;j++) { if(mark[j]==1) continue; else { if(!match(s[j],s[i],j)) { mmax=i+1; break; } } } if(mmax!=0)break; } printf("Case #%d: ",z++); if(mmax==0)printf("-1\n"); else printf("%d\n",mmax); } return 0; }