传送门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; }