首先看题,题目要求我们求最长匹配的长度,我们不妨如下思考:
对于字符串S,我们从第y位开始搜索(保证前y-1位一定可以是匹配)
从第y位开始生成字符串,若此时生成的字符串在P中出现过,则证明
此时的字符串可以被匹配到y+i的位置,我们再从y+i+1开始搜索便好了!
而问题的答案就是我们已到达的最大的一个y。
那么问题来了,如果按照上述说法搜索,复杂度不稳定,但一定会
超时的,有木有什么优化呢?
答案是有的(不然我写这个题解干什么呢?),我们注意到,如果
对于此时的y,我们曾经到达过,虽然到达的方式不同,但我们到达过,后
面我们进行搜索的过程与结果肯定是一样的,所以,我们就跳过就好啦!
而总的复杂度最高位O(n)(n为S串的长度),一下便是完整代码(加了点小优
化):
#include<bits/stdc++.h> using namespace std; map<string,bool>s;//一个map解千愁~就是<u>**速度慢了点**</u>,大佬请自行打**hash** int x; int ans=0; int ams=0; string l; bool F=0; bool come[200001]; inline void to_search(int now){ if(come[now]){//如果曾经搜索过此时的‘y’ return;//退出 } come[now]=1;//标记搜索过此时的‘y’ if(now==x){ return; } string qu=""; for(int i=now;i<x;++i){ if(i-now>=ams){//如果现在加的元素大于了最长元素,之后一定不可能成立,于是跳过(虽然是小优化,也很强大有不有~) return; } qu+=l[i]; if(s[qu]){//如果P集合中有此时的元素 F=1;//判断成立 if(i>ans){//记录答案 ans=i; } to_search(i+1);//从下一个y开始搜索 } } } int main(){ int e=1; while(cin>>l){ if(l=="."){ break; } s[l]=1;//标记元素存在 if(l.size()>ams){ ams=l.size();//记录最长元素(小优化第一步) } } string yu=""; while(cin>>l){//输入字符串S yu+=l;//将字符串S整合 } l=yu; x=l.size();//得到S的长度 to_search(0);//从第一个字符开始搜索 if(!F){//注意判断是否搜索过,第一个点的坑QWQ printf("0"); return 0; } printf("%d",ans+1);//输出答案(记得加一,因为是从0开始搜的) return 0; }