SPOJ-LCS Longest Common Substring 【后缀自动机】

本文深入探讨了如何通过构建特殊的树形数据结构来优化字符串匹配算法,特别关注于使用未出现过的字符进行拼接,以寻找right集合的最小和最大值,从而在字符串中快速定位目标子串。文章详细介绍了算法的实现过程,包括关键的数据结构定义、函数设计及其实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目分析:

用没出现过的字符搞拼接。搞出right树,找right集合的最小和最大。如果最小和最大分居两侧可以更新答案。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 1000500;
 5 
 6 int son[maxn][30],fa[maxn],maxlen[maxn],root,num,sigma = 27;
 7 int minn[maxn],maxx[maxn];// lright rright
 8 
 9 string str,ss;
10 int n,m;
11 vector<int> T[maxn];
12 
13 int addnew(int dt){maxlen[++num] = dt;return num;}
14 int ins(char x,int p,int hhhh){
15     int np = addnew(maxlen[p]+1); minn[np] = maxx[np] = hhhh;
16     while(p && !son[p][x-'a']) son[p][x-'a'] = np,p = fa[p];
17     if(!p){fa[np] = root; return np;}
18     else{
19     int q = son[p][x-'a'];
20     if(maxlen[q]==maxlen[p]+1){fa[np]=q;return np;}
21     else{
22         int nq = addnew(maxlen[p]+1);
23         for(int i=0;i<sigma;i++) son[nq][i] = son[q][i];
24         fa[nq] = fa[q]; fa[q] = fa[np] = nq;
25         while(p && son[p][x-'a'] == q) son[p][x-'a'] = nq,p = fa[p];
26         return np;
27     }
28     }
29 }
30 
31 void dfs(int now){
32     if(!minn[now]) minn[now] = 1e9;
33     for(int i=0;i<T[now].size();i++){
34     dfs(T[now][i]);
35     minn[now] = min(minn[now],minn[T[now][i]]);
36     maxx[now] = max(maxx[now],maxx[T[now][i]]);
37     }
38 }
39 
40 void work(){
41     int lst = addnew(0);root = lst;
42     for(int i=0;i<str.length();i++)
43     lst = ins(str[i],lst,i+1);
44     for(int i=2;i<=num;i++) T[fa[i]].push_back(i);
45     dfs(1); int ans = 0;
46     for(int i=1;i<=num;i++)if(minn[i]<=n&&maxx[i]>n+1)ans=max(ans,maxlen[i]);
47     cout<<ans<<endl;
48 }
49 
50 int main(){
51     ios::sync_with_stdio(false);
52     cin.tie(0);
53     cin >> str; cin >> ss;
54     n = str.length(); m = ss.length();
55     str += ('z'+1); str += ss;
56     work();
57     return 0;
58 }

 

转载于:https://www.cnblogs.com/Menhera/p/10306444.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值