题目大意:首先给你一下母串,长度不超过10^5,然后有 N(10^5) 次查询,每次查询有两种命令,0或者1,然后加一个子串,询问母串里面有多少个子串,0表示可以重复,1表示不可以重复。
 
分析:发现查询的次数是比较多的,然后可以利用查询的串建立一个trie,然后用母串跑一遍就行了,不过有两种操作比较麻烦一些,不过我们可以保存查询时每个节点的查询结果,然后每个串都对应一个节点,最后输出查询结果即可,这样也可以规避掉重复串的问题。
 
代码如下:
===============================================================================================================
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std; const int MAXN = 6e5+;
const int MaxSon = ; char MumStr[MAXN];
int Num[MAXN], op[MAXN]; struct Ac_Trie
{
int next[MAXN][MaxSon];
int Fail[MAXN];
///End保存每个单词匹配成功后最后面的位置
///如果这个节点是一个单词,Len保存这个单词的长度
int End[MAXN], Len[MAXN];
int ans[MAXN][];///保存两种状态的答案
int root, cnt; int newnode()
{
for(int i=; i<MaxSon; i++)
next[cnt][i] = -;
Len[cnt] = Fail[cnt] = false;
End[cnt] = -;
ans[cnt][] = ans[cnt][] = ; return cnt++;
}
void InIt()
{
cnt = ;
root = newnode();
}
int Insert(char s[])
{///返回这个字符串对应的节点编号
int i, now = root; for(i=; s[i]; i++)
{
int k = s[i] - 'a'; if(next[now][k] == -)
next[now][k] = newnode();
now = next[now][k];
} Len[now] = i; return now;
}
void GetFail()
{
queue<int> Q;
int i, now = root; for(i=; i<MaxSon; i++)
{
if(next[now][i] == -)
next[now][i] = root;
else
{
Fail[next[now][i]] = root;
Q.push(next[now][i]);
}
} while(Q.size())
{
now = Q.front();
Q.pop(); for(i=; i<MaxSon; i++)
{
if(next[now][i] == -)
next[now][i] = next[Fail[now]][i];
else
{
Fail[next[now][i]] = next[Fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
void Query(char MumStr[])
{
int i, now = root, temp; for(i=; MumStr[i]; i++)
{
int k = MumStr[i] - 'a'; now = next[now][k]; if(!now)continue; temp = now; while(temp != root)
{
if(Len[temp])
ans[temp][]++;
if(Len[temp] && (i-End[temp] >= Len[temp]) )
ans[temp][]++, End[temp] = i; temp = Fail[temp];
}
}
}
};
Ac_Trie ac;
int main()
{
int i, M, t=; while(scanf("%s", MumStr) != EOF)
{
char s[];
ac.InIt(); scanf("%d", &M); for(i=; i<=M; i++)
{
scanf("%d%s", &op[i], s);
Num[i] = ac.Insert(s);
} ac.GetFail();
ac.Query(MumStr); printf("Case %d\n", t++);
for(i=; i<=M; i++)
printf("%d\n", ac.ans[Num[i]][op[i]]);
printf("\n");
} return ;
}

最新文章

  1. 客户端的验证插件validator
  2. AMap编辑折线、多边形、圆
  3. linux使用rpm重装jdk
  4. ThinkPHP上传返回 “文件上传保存错误!”
  5. 自动选中div中的文字
  6. JAVA利用ODBC读取DBF,可以解决javadbf.jar对DBF部分中文乱码和错行等杂症
  7. 编译安装-Nginx
  8. string和stringBuilder的区别
  9. HDU 3046 Pleasant sheep and big big wolf(最小割)
  10. HDU ACM 1088 Write a simple HTML Browser
  11. 浙大pat1009题解
  12. 透过源码看看Redis中如何计算QPS
  13. ubuntu 切换到ROOT权限
  14. windows下面配合thinkphp5.1.7的nginx.conf内容
  15. PHP文件管理—实现网盘以及压缩包的功能操作
  16. Intellij IDEA 解决 Maven 依赖下载慢的问题
  17. Jmeter分布式及在Linux上执行jmeter脚本
  18. memcache、redis原理对比
  19. swift 基本用法
  20. Android Studio自定义组合控件

热门文章

  1. Signalr简单入门,使用注意点
  2. Win10获取管理员/administrator权限的方法
  3. iOS中JavaScript和OC交互
  4. angular.js 字符串1
  5. table强制不换行
  6. SGU 118.Digital root
  7. 做了一个类似天猫鼠标经过icon的动画,记录一下
  8. js创建对象的三种方法:文本标识法和构造器函数法和返回对象的函数
  9. PHP面向对象(OOP):.static和const关键字的使用(self::)
  10. linux下shapely的安装