FZU 2108(AC自动机)

本文介绍了一种使用AC自动机结合动态规划解决特定字符串匹配问题的方法。通过构建AC自动机并利用DP记录状态,实现了寻找不包含特定模式的最长子串长度的功能。

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

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;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值