fzu2108/ xmut1180
Description
给定一个字符串S,问S的子串中不包含A1,A2...AN的最长子串有多长。
Input
第一行为字符串S,字符串S的长度为B( 1 <= B <= 100000 ),第二行是不能包含的子串个数N( 1 <= N<= 1000 )。接下来N行字符串,每个字符串长度不超过C( 1 <= C <= 100 )。
所有字符串由小写的英文字符组成。
Output
最长子串的长度。
Sample Input
lgcstraightlalongahisnstreet
5
str
long
tree
biginteger
ellipse
Sample Output
12
思路:AC自动机+dp
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int maxn = (int)1e6 + 10;
const int inf = 0x3f3f3f;
struct Trie {
int node[maxn][26], fail[maxn], num[maxn], root, L;
int dp[maxn];
int newnode() {
for(int i = 0; i < 26; i++) node[L][i] = -1;
num[L] = inf;
return L++;
}
void init() {
L = 0;
root = newnode();
}
void insert(char buf[]) {
int len = strlen(buf);
int now = root;
for(int i = 0; i < len; i++) {
if(node[now][buf[i] - 'a'] == -1)
node[now][buf[i] - 'a'] = newnode();
now=node[now][buf[i] - 'a'];
}
num[now] = len;
}
void build() {
queue<int> q;
for(int i = 0; i < 26; i++) {
if(node[root][i] == -1)
node[root][i] = root;
else
fail[node[root][i]] = root, q.push(node[root][i]);
}
while(!q.empty()) {
int now = q.front();
q.pop();
for(int i = 0; i < 26; i++) {
if(node[now][i] == -1)
node[now][i] = node[fail[now]][i];
else {
fail[node[now][i]] = node[fail[now]][i];
q.push(node[now][i]);
num[now] = min(num[now], num[fail[now]]);
}
}
}
}
int query(char buf[]) {
int now = root, ans = 0;
dp[0] = 0;
for(int i = 1; buf[i]; i++) {
dp[i] = dp[i-1] + 1;
now = node[now][buf[i] - 'a'];
dp[i]=min(dp[i], num[now] - 1);
ans=max(ans, dp[i]);
}
return ans;
}
};
Trie ac;
char buf[maxn];
char s[maxn];
int main() {
int n;
scanf("%s",buf + 1);
scanf("%d",&n);
ac.init();
for(int i =1 ; i <= n;i++) {
scanf("%s",s);
ac.insert(s);
}
ac.build();
int ans = ac.query(buf);
printf("%d\n",ans);
return 0;
}