hdu1686 Oulipo KMP/AC自动机
The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book:
Tout avait Pair normal, mais tout s’affirmait faux. Tout avait Fair normal, d’abord, puis surgissait l’inhumain, l’affolant. Il aurait voulu savoir où s’articulait l’association qui l’unissait au roman : stir son tapis, assaillant à tout instant son imagination, l’intuition d’un tabou, la vision d’un mal obscur, d’un quoi vacant, d’un non-dit : la vision, l’avision d’un oubli commandant tout, où s’abolissait la raison : tout avait l’air normal mais…
Perec would probably have scored high (or rather, low) in the following contest. People are asked to write a perhaps even meaningful text on some subject with as few occurrences of a given “word” as possible. Our task is to provide the jury with a program that counts these occurrences, in order to obtain a ranking of the competitors. These competitors often write very long texts with nonsense meaning; a sequence of 500,000 consecutive 'T's is not unusual. And they never use spaces.
So we want to quickly find out how often a word, i.e., a given string, occurs in a text. More formally: given the alphabet {'A', 'B', 'C', …, 'Z'} and two finite strings over that alphabet, a word W and a text T, count the number of occurrences of W in T. All the consecutive characters of W must exactly match consecutive characters of T. Occurrences may overlap.
题意:给出了两个字符串,问第一个串在第二个中可以重复地出现过多少次。
我一开始是用AC自动机做了一次,建了模式串的AC自动机后,待匹配串每次走到词尾节点ans++。
后来又用KMP做了一次,先模式串自匹配,再与待匹配串匹配的时候记录ans
// 有nxt数组版本。。该程序不能判别相同模式串,因此若模式串重复,答案会将相同模式串当做不同的处理,因此若需要可以用map去重或修改insert
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxm=; //maxm是总结点数:约为字母数+++ char s[],word[];
int nxt[maxm][],tail[maxm],f[maxm],size; //nxt是结点指向不同字母的结点下标,tail是表示该结点为几个单词的词尾(可能需要计算重复的模式串情况),f是当不匹配时转跳到的结点下标,size是结点数
int last[maxm]; //last指针是指向上一个是单词结尾的结点,由于是由失配指针拓展得到的,因此所指向的单词都是该结点表示的单词的后缀单词,但由于可能卡空间,所以虽然可以在时间上优化,但是有时并不使用 int newnode(){ //初始化整个trie或建立新的结点时,首先初始化当前结点所指向的26个字母的结点为0,表示暂时还没有指向的字母,然后暂定该结点不是单词尾结点,暂无失配时转跳位置(即转跳到根节点),返回结点标号
memset(nxt[size],,sizeof(nxt[size]));
f[size]=tail[size]=;
return size++;
} void insert(char s[]){ //构造trie,p为当前结点的上一个结点标号,初始为0;x即为当前结点(上个结点标号指向当前字母的结点)标号,若此结点还未出现过,那么就建立这个结点;然后更新p为当前结点标号以便后续操作
int i,p=;
for(i=;s[i];i++){
int &x=nxt[p][s[i]-'A'];
p=x?x:x=newnode();
}
tail[p]++; //此时仅将s串记录,即将s串结尾的结点加1,若无相同模式串,则此操作只会使所有串尾结点的tail值由0变为1,但有相同模式串,则会重复记录,需要去重可以用map或用tail[p]=1;语句来完成
} void makenxt(){ //利用bfs来构造失配指针
int i;
queue<int>q;
f[]=;
for(i=;i<;i++){ //首先将0结点(根节点)连接的字母结点加入队列,并定失配指针和last指针都指向0结点
int v=nxt[][i];
if(v){
f[v]=last[v]=;
q.push(v);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(i=;i<;i++){
int v=nxt[u][i];
if(!v)nxt[u][i]=nxt[f[u]][i]; //当u结点没有i对应字母,则视为失配,将其指向失配后转跳到的结点所指向的i对应字母
else{
q.push(v); //u结点存在指向i的结点,则将所指向的结点下标加入队列
f[v]=nxt[f[u]][i]; //设置这个结点的失配指针指向上个结点失配后的指向字母i的结点,由于bfs一定会从字典树浅层到深层,即从字符串短到长,而失配转跳后表示的字符串长度严格减少,所以只需要指向一次即可
last[v]=tail[f[v]]?f[v]:last[f[v]]; //若失配指针指向的结点是单词结尾,那么当前结点失配后就可以直接指向失配结点,即失配路径上的上一个单词结点,若失配结点不是单词结尾,就指向失配结点的last
}
}
}
} int query(char s[]){ //查询s串中模式串出现了多少种/次
int ans=,v=;
for(int i=;s[i];i++){
while(v&&!nxt[v][s[i]-'A'])v=f[v];
v=nxt[v][s[i]-'A'];
int tmp=v;
while(tmp){
ans+=tail[tmp];
tmp=last[tmp];
}
}
return ans;
} int main(){
int T;
scanf("%d",&T);
while(T--){
size=,newnode();
scanf("%s",word);
insert(word);
makenxt();
scanf("%s",s);
printf("%d\n",query(s));
}
return ;
}
AC自动机
#include<stdio.h>
#include<string.h> char s[],t[]; //s为待匹配串,t为模板串
int p[]; //自匹配数组 int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%s%s",t,s);
int n=strlen(s);
int m=strlen(t);
int i,j,ans=;
p[]=p[]=;
for(i=;i<m;i++){
j=p[i];
while(j&&t[i]!=t[j])j=p[j];
p[i+]=t[i]==t[j]?j+:;
}
j=;
for(i=;i<n;i++){
while(j&&s[i]!=t[j])j=p[j];
if(s[i]==t[j])j++;
if(j==m)ans++;
}
printf("%d\n",ans);
}
return ;
}
KMP
hdu1686 Oulipo KMP/AC自动机的更多相关文章
- 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机
为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定 ...
- Trie树&kmp&AC自动机&后缀数组&Manacher
Trie 计数+Trie,读清题意很重要 https://vjudge.net/problem/UVALive-5913 kmp AC自动机 模板:https://vjudge.net/problem ...
- 2021.11.09 P4824 [USACO15FEB]Censoring S与P3121 [USACO15FEB]Censoring G(KMP&&AC自动机)
2021.11.09 P4824 [USACO15FEB]Censoring S与P3121 [USACO15FEB]Censoring G(KMP&&AC自动机) https://w ...
- 关于Trie KMP AC自动机
个人认为trie,KMP,AC自动机是思想非常明确的,AC自动机的性质是与KMP算法的思想类似的(失配后跳转) 而KMP是线性的,AC自动机是在tire树上跑KMP,为方便那些不会用指针的小朋友(我也 ...
- 「模拟赛20180306」回忆树 memory LCA+KMP+AC自动机+树状数组
题目描述 回忆树是一棵树,树边上有小写字母. 一次回忆是这样的:你想起过往,触及心底--唔,不对,我们要说题目. 这题中我们认为回忆是这样的:给定 \(2\) 个点 \(u,v\) (\(u\) 可能 ...
- KMP & AC自动机
KMP void kmp(char t[],char p[]) { int n=strlen(t),m=strlen(p); int *f=new int[m]; f[0]=f[1]=0; for(i ...
- hdu1686 Oulipo kmp
题目传送门 思路:kmp模板,稍微修改下 #include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using name ...
- 优先队列 + 并查集 + 字典树 + 欧拉回路 + 树状数组 + 线段树 + 线段树点更新 + KMP +AC自动机 + 扫描线
这里给出基本思想和实现代码 . 优先队列 : 曾经做过的一道例题 坦克大战 struct node { int x,y,step; friend bool operator <(no ...
- AC自动机【萌新文章】
我这个蒟蒻第一次写博客,有点小激动呢. 主要是最近刚学了AC自动机,学得糟糟糕糕,记录一下,看到dalao们都在写博客,决定自己也写一波[我好水的啦,写的也不好] AC自动机大概就是 Trie+ ...
随机推荐
- bzoj1692
题解: 二分最近的不相同 然后hash判断是否相同 然后贪心 代码: #include<bits/stdc++.h> using namespace std; #define ull un ...
- jsp标签之jsp:setProperty用法
参考:http://blog.csdn.net/wanghaishanren/article/details/2047400
- C++输出数组名
1.如果C++输出的数组是char类型的,那么输出的就是数组中的元素. 2.如果使用的是其他类型的数组作为输出的话,那么就是一个16进制的地址. 3.还是那句话,对数组的操作,很多时候都是指针的操作, ...
- datatabale 服务器分页
转载:http://blog.csdn.net/angelvyvyan/article/details/51783272$(document).ready( function() { $('#tabl ...
- 2.1FTP的简单传输
第一个简单的FTP传输实例 from ftplib import FTP nonpassive = False filename = 'new_1.py' dirname = '.' sitename ...
- μC/OS-II在Microblaze上的移植与使用专题--“安富利杯”赛灵思FPGA设计技巧与应用创新博文大赛参赛作品
reference:http://xilinx.eetrend.com/d6-xilinx/blog/2010-05/682.html 随着集成电路设计与制造技术的发展,FPGA芯片的容量越来越大 ...
- Java读取键盘输入
三种方法分别如下: 方法一:从控制台接收一个字符,然后将其打印出来 import java.io.*; public static void main(String [] args) throws I ...
- Mybatis学习笔记三
一.延迟加载 延迟加载即加载延迟了,并不是一次性加载完而是按需加载,感觉应该是针对多表查询而言的,即先查询单表等需要另一张表的信息时再去加载,这样能提高数据库的性能: 需要注意的是,mybatis提供 ...
- SpringSecurity入门例子及遇到的问题解决
最近学习<Spring 实战>学习到了SpringSecurity,觉得书本上的例子过于复杂,而且不喜欢它基于java配置,更喜欢用xml文件进行配置 于是在极客学院网上学习,感觉挺不错的 ...
- python 正则匹配时间格式转换方法
import re from datetime import datetime a = '2018年8月9日 10:10' s = re.findall('\d+',a) print(s) d = ' ...