题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3228
题目大意:给你一个字符串,再给你一些子串,问你子串在主串中的出现的情况,一种是可叠加出现,一种是不可叠加出现
思路:对于第一种情况,就是直接来个AC自动机就解决的事,对于第二种情况,我们加一个判断是否重叠就好了,当前字符位置 — last[当前节点] <= deep[当前节点],这道题就是练习一下对于AC自动机中kmp + Trie思想的使用。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
char str[maxn], word[20];
int temp[maxn], pos[maxn]; // pos记录子串在Trie中的结束点
int idx(char c){return c - 'a';}
struct Trie
{
int next[6*maxn][26], fail[6*maxn], last[6*maxn]; //last记录当前节点的上一个匹配位置
int deep[6*maxn]; //记录当前节点的字符在模式串中的位置
int cnt[6*maxn][2];
int root, L;
int newnode()
{
for(int i = 0; i < 26; ++i)
next[L][i] = -1;
L++;
return L-1;
}
void init()
{
L = 0;
root = newnode();
deep[root] = 0;
}
int insert(char word[])
{
int len = strlen(word), now = root;
for(int i = 0; i < len; ++i){
int c = idx(word[i]);
if(next[now][c] == -1){
next[now][c] = newnode();
deep[next[now][c]] = i+1;
}
now = next[now][c];
}
return now; //返回串结束点
}
void build() //BFS建图和失配数组
{
queue<int> q;
fail[root] = root;
for(int i = 0; i < 26; ++i){
if(next[root][i] == -1)
next[root][i] = root;
else{
fail[next[root][i]] = root;
q.push(next[root][i]);
}
}
while(!q.empty()){
int now = q.front();
q.pop();
for(int i = 0; i < 26; ++i){
if(next[now][i] == -1)
next[now][i] = next[fail[now]][i];
else{
fail[next[now][i]] = next[fail[now]][i];
q.push(next[now][i]);
}
}
}
}
void query(char word[])
{
int len = strlen(word), now = root;
memset(cnt, 0, sizeof(cnt));
memset(last, -1, sizeof(last));
for(int i = 0; i < len; ++i){
int c = idx(word[i]);
now = next[now][c];
int tmp = now;
while(tmp != root){
cnt[tmp][0]++;
if(i - last[tmp] >= deep[tmp]){ //对于是否重叠的判断
last[tmp] = i;
cnt[tmp][1]++;
}
tmp = fail[tmp];
}
}
}
}trie;
int main()
{
int n, cas = 0;
while(~scanf("%s", str)){
cas++;
printf("Case %d\n", cas);
scanf("%d", &n);
trie.init();
for(int i = 0; i < n; ++i){
scanf("%d %s", &temp[i], word);
pos[i] = trie.insert(word);
}
trie.build();
trie.query(str);
for(int i = 0; i < n; ++i)
cout << trie.cnt[pos[i]][temp[i]] << '\n';
cout << '\n';
}
return 0;
}