第一行给一个整数,表示有几个案例。
每个案例先给出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;
}