kuangbin ac自动机 常用打印

第一行给一个整数,表示有几个案例。
每个案例先给出1个整数,表示有几个短字符串。
在每个案例的最后再给出长字符。
每个案例输出一行整数,表示短字符串里有几个能在长字符里找到。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<stack>
#include<set>
#include<queue>
#include<vector>
#include<stdlib.h>
 
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
 
#define inf 0x3f3f3f3f
#define cha 1e-6
#define ll long long    
using namespace std;
const int maxn=1e6+6;
int trie[maxn][26];
int cntword[maxn];
int fail[maxn];//失配指针
int cnt=0;
void insert(string s){
    int root=0;
    for(int i=0;i<s.size();i++){
        int x=s[i]-'a';

        if(trie[root][x]==0){
            trie[root][x]=++cnt;
        }
        root=trie[root][x];
    }
    cntword[root]++;
}

void getfail(){
    queue<int>qu;
    for(int i=0;i<26;i++){
        if(trie[0][i]){
            fail[trie[0][i]]=0;
            qu.push(trie[0][i]);
        }
    }
    while(!qu.empty()){
        int now=qu.front();
        qu.pop();
        for(int i=0;i<26;i++){
            if(trie[now][i]){
                fail[trie[now][i]]=trie[fail[now]][i];
                qu.push(trie[now][i]);
            }
            else{
                trie[now][i]=trie[fail[now]][i];
            }
        }
    }
}

int query(string s){
    int now=0,ans=0;
    for(int i=0;i<s.size();i++){
        now=trie[now][s[i]-'a'];
        for(int j=now;j&&cntword[j]!=-1;j=fail[j]){//已经访问过
            ans+=cntword[j];
            cntword[j]=-1;
        }
    }
    return ans;
}

int main(){
    ios::sync_with_stdio(false);
    int n;
    int t;
    cin>>t;
    while(t--){
        memset(trie,0,sizeof(trie));
        memset(cntword,0,sizeof(cntword));
        cin>>n;
        string s;
        for(int i=0;i<n;i++){
            cin>>s;
            insert(s);
        }
        fail[0]=0;
        getfail();
        cin>>s;
        cout<<query(s)<<endl;
    }
    return 0;

}

第一行,一个整数N(1<=N<=500),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在20—200之间。
每个病毒都有一个编号,依此为1—N。
不同编号的病毒特征码不会相同。
在这之后一行,有一个整数M(1<=M<=1000),表示网站数。
接下来M行,每行表示一个网站源码,源码字符串长度在7000—10000之间。
每个网站都有一个编号,依此为1—M。
以上字符串中字符都是ASCII码可见字符(不包括回车)。
Output
依次按如下格式输出按网站编号从小到大输出,带病毒的网站编号和包含病毒编号,每行一个含毒网站信息。
web 网站编号: 病毒编号 病毒编号 …
冒号后有一个空格,病毒编号按从小到大排列,两个病毒编号之间用一个空格隔开,如果一个网站包含病毒,病毒数不会超过3个。
最后一行输出统计信息,如下格式
total: 带病毒网站数
冒号后有一个空格。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<stack>
#include<set>
#include<queue>
#include<vector>
#include<stdlib.h>
 
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
 
#define inf 0x3f3f3f3f
#define cha 1e-6
#define ll long long    
using namespace std;
const int maxn=1e5+5;
int trie[maxn][130];
int cntword[maxn];
int fail[maxn];//失配指针
int tag[maxn],s1[maxn];
int vis[maxn];
int cnt,ans,number,d,tol;

void insert(string s){
    int root=0;
    for(int i=0;i<s.size();i++){
        int x=s[i];
        if(trie[root][x]==0){
            trie[root][x]=++cnt;
        }
        root=trie[root][x];
    }
    cntword[root]++;
    tag[root]=++number;
}

void getfail(){
    queue<int>qu;
    for(int i=0;i<130;i++){
        if(trie[0][i]){
            fail[trie[0][i]]=0;
            qu.push(trie[0][i]);
        }
    }
    while(!qu.empty()){
        int now=qu.front();
        qu.pop();
        for(int i=0;i<130;i++){
            if(trie[now][i]){
                fail[trie[now][i]]=trie[fail[now]][i];
                qu.push(trie[now][i]);
            }
            else{
                trie[now][i]=trie[fail[now]][i];
            }
        }
    }
}

void query(string s){
    int now=0;
    for(int i=0;i<s.size();i++){
        now=trie[now][s[i]];
        for(int j=now;j&&vis[j]!=1;j=fail[j]){
             ans+=cntword[j];
             if(cntword[j]>0) s1[d++]=tag[j];
             vis[j]=1;
        }
    }
}

int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    string s;
    for(int i=1;i<=n;i++){
        cin>>s;
        insert(s);
    }
    getfail();
    int t;
    cin>>t;
    for(int i=1;i<=t;i++){
        memset(vis,0,sizeof(vis));
        memset(s1,0,sizeof(s1));
        ans=0,d=0;
        cin>>s;
        query(s);
        if(ans){
            tol++;
            printf("web %d:",i);
            sort(s1,s1+d);
            for(int j=0;j<d;j++){
                printf(" %d",s1[j]);
            }
            cout<<endl;
        }
    }    
    printf("total: %d\n",tol);
    return 0;

}

第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。
接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。
在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。
Output
按以下格式每行一个,输出每个病毒出现次数。未出现的病毒不需要输出。
病毒特征码: 出现次数
冒号后有一个空格,按病毒特征码的输入顺序进行输出。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
#include<stack>
#include<set>
#include<queue>
#include<vector>
#include<stdlib.h>
 
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<cstdlib>
 
#define inf 0x3f3f3f3f
#define cha 1e-6
#define ll long long    
using namespace std;
const int maxn=50004;
int trie[maxn][130];
int cnt[maxn];
int fail[maxn];//失配指针
int tag[maxn],s1[maxn];
int vis[maxn],num[maxn];
char p[1003][55],s[2000006];
int ans,number,d,tol,pos;

void insert(int idx){
    int lp=strlen(p[idx]),root=0;
    for(int i=0;i<lp;i++){
        int x=p[idx][i];
        if(trie[root][x]==0){
            trie[root][x]=++pos;
        }
        root=trie[root][x];
    }
    num[root]=idx;
}

void getfail(){
    queue<int>qu;
    for(int i=0;i<130;i++){
        if(trie[0][i]){
            fail[trie[0][i]]=0;
            qu.push(trie[0][i]);
        }
    }
    while(!qu.empty()){
        int now=qu.front();
        qu.pop();
        for(int i=0;i<130;i++){
            if(trie[now][i]){
                fail[trie[now][i]]=trie[fail[now]][i];
                qu.push(trie[now][i]);
            }
            else{
                trie[now][i]=trie[fail[now]][i];
            }
        }
    }
}

void query(){
    int now=0,ls=strlen(s);
    for(int i=0;i<ls;i++){
        now=trie[now][s[i]];
        for(int j=now;j;j=fail[j]){
            cnt[num[j]]++;
        }
    }
}

int main(){
    ios::sync_with_stdio(false);
    int n;
    while(cin>>n){
        memset(trie,0,sizeof(trie));
        memset(cnt,0,sizeof(cnt));
        memset(num,0,sizeof(num));
        pos=0;
        for(int i=1;i<=n;i++){
            cin>>p[i];
            insert(i);
        }
        getfail();
        cin>>s;
        query();
        for(int i=1;i<=n;i++){
            if(cnt[i])
                printf("%s: %d\n",p[i],cnt[i]);
        }
    }
    return 0;

}

First line contains two integer m (0 <= m <= 10), n (1 <= n <=2000000000). Here, m is the number of genetic disease segment, and n is the length of sequences.

Next m lines each line contain a DNA genetic disease segment, and length of these segments is not larger than 10.
Output
An integer, the number of DNA sequences, mod 100000.
Sample Input
4 3
AT
AC
AG
AA
Sample Output
36

#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
const int maxn = 102;
const int mod = 100000;
int trie[maxn][4], fail[maxn], tail[maxn];
int  n, m, pos;
char s[15];
map<char, int>idx;
void insert() {
	int ls = strlen(s), u = 0;
	for (int i = 0; i < ls; i++) {
		int v = idx[s[i]];
		if (trie[u][v] == 0)
			trie[u][v] = ++pos;
		u = trie[u][v];
	}
	tail[u] = 1;
}
void getfail() {
	queue<int>q;
	for (int i = 0; i < 4; i++) {
		if (trie[0][i]) {
			fail[trie[0][i]] = 0;
			q.push(trie[0][i]);
		}
	}
	while (!q.empty()) {
		int cur = q.front();
		q.pop();
		for (int i = 0; i < 4; i++) {
			if (trie[cur][i]) {
				fail[trie[cur][i]] = trie[fail[cur]][i];
				q.push(trie[cur][i]);
			}
			else trie[cur][i] = trie[fail[cur]][i];
			tail[trie[cur][i]] |= tail[trie[fail[cur]][i]]; //注意是或,只要包含病毒就不行
		}
	}
}
struct matrix {
	long long a[maxn][maxn];
	matrix() {
		memset(a, 0, sizeof(a));
	}
};
matrix  operator*(const matrix& x, const matrix& y) {
	matrix  m;
	for (int i = 0; i <= pos; ++i) 
		for (int j = 0; j <= pos; ++j) 
			for (int k = 0; k <= pos; ++k) 
				m.a[i][j] = (m.a[i][j] + x.a[i][k] * y.a[k][j]) % mod;
	return m;
}
matrix fastm(matrix a, int n) {
	matrix res;
	for (int i = 0; i <= pos; ++i) res.a[i][i] = 1;
	while (n) {
		if (n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}
int main() {
	idx['A'] = 0, idx['C'] = 1;
	idx['T'] = 2, idx['G'] = 3;
	while (~scanf("%d%d", &m, &n)) {
		pos = 0;
		memset(trie, 0, sizeof(trie));
		memset(tail, 0, sizeof(tail));
		while (m--) {
			scanf("%s", s);
			insert();
		}
		getfail();
		matrix x;
		for (int i = 0; i <= pos; ++i)  //构建初始矩阵
			if (!tail[i]) //如果本身不含病毒
				for (int j = 0; j < 4; ++j)
					if (!tail[trie[i][j]]) //其子节点也不含病毒
						x.a[i][trie[i][j]]++; //那么节点i到该子节点是可行方案+1
		x = fastm(x, n);
		int ans = 0;
		for (int i = 0; i <= pos; ++i)	//统计
			ans = (ans + x.a[0][i]) % mod;
		printf("%d\n", ans);
	}
	return 0;
}
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值