题解 P1470 【最长前缀 Longest Prefix】

 首先看题,题目要求我们求最长匹配的长度,我们不妨如下思考:

​ 对于字符串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; }

转载于:https://www.cnblogs.com/ThinkofBlank/p/10146136.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值