题意:给你n个串,让你找到一个串,这个串的前面至少有一个不是它的子串,并且这个串要尽量靠后。
思路:弄两个变量当做指针来使,定义变量名为 l 和 r ,然后线性地往后面扫,如果s[l]不是s[r]的子串,就让后面的那个指针往后走,然后再从 l 扫到 r,如果s[l]是s[r]子串,继续从 l 扫到 r。这样时间复杂度就没有n^2了。为什么可以这样线性地走呢,因为,如果s[l]是s[l+1]的子串,s[l+1]是s[l+2]的子串,那么s[l]肯定就是s[l+2]的子串了,所以不用重复扫了。
P.S.一开始很傻地用了n^2做,然后果断超时,然后看到别人的博客,说要用到双指针,然后还是很傻地,如果是子串就两个都往后,如果不是就后面的那么往后面走,然而,这是错的,而且反过来了······看了题解还是那么傻傻地把代码搞错了······
1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<math.h> 5 #include<algorithm> 6 #include<vector> 7 #include<string> 8 #include<queue> 9 #include<map> 10 #include<stack> 11 #include<set> 12 #define ll long long 13 #define PI acos(-1.0) //圆周率 14 const int mod=1e9+7; 15 const int maxn=1e6+10; 16 using namespace std; 17 int T,n; 18 char s[510][2010]; 19 int f[2010]; 20 void getnext(char *a) 21 { 22 memset(f,0,sizeof(f)); 23 int len=strlen(a); 24 int i=0; 25 int j=-1; 26 f[0]=-1; 27 while(i<len) 28 { 29 if(j==-1||a[i]==a[j]) 30 { 31 i++; 32 j++; 33 f[i]=j; 34 } 35 else j=f[j]; 36 } 37 // for(int i=0;i<len;i++) cout<<f[i]<<" "; cout<<endl; 38 } 39 bool judge(char *a,char *b) 40 { 41 int lena=strlen(a); 42 int lenb=strlen(b); 43 44 getnext(b); 45 int i=0; 46 int j=0; 47 while(i<lena) 48 { 49 if(j==-1||a[i]==b[j]) 50 { 51 i++; 52 j++; 53 } 54 else j=f[j]; 55 if(j==lenb) return true; 56 } 57 return false; 58 } 59 int main() 60 { 61 int cas=0; 62 scanf("%d",&T); 63 while(T--) 64 { 65 scanf("%d",&n); 66 for(int i=0;i<n;i++) scanf("%s",s[i]); 67 68 int l=0; 69 int ans=-1; 70 for(int i=1;i<n;i++) 71 { 72 while(l<i) 73 { 74 if(judge(s[i],s[l])) l++; 75 else 76 { 77 ans=i+1; 78 break; 79 } 80 } 81 } 82 83 printf("Case #%d: %d ",++cas,ans); 84 } 85 86 return 0; 87 }