[kuangbin带你飞]专题十七 AC自动机 D Detect the Virus
来源:互联网 发布:windows怎么修改快捷键 编辑:程序博客网 时间:2024/06/05 10:00
https://vjudge.net/contest/70326#problem/D
题意:给出n个编码后的模板串,然后有M次询问,每次询问输入一个编码后的文本串,问在编码前,有多少个模板串在文本串中出现过。
所以本题的烦点在于还原的过程,由于解码后的字符的ASCII值是从0~255的,所以不能用strlen,得自己记录长度。
自己模拟太烦了,看了bin神的结题报告才懂可以写的这么简洁,思路是以4个原字母为单位 (因为需要6-位>8位 那么四个字母会最终转化为三个字母) 。
void change(unsigned char str[],int len){ int t=0; for(int i=0;i<len;i+=4) { buf[t++]=((str[i]<<2)|(str[i+1]>>4)); if(i+2 < len) buf[t++]=( (str[i+1]<<4)|(str[i+2]>>2) ); if(i+3 < len) buf[t++]= ( (str[i+2]<<6)|str[i+3] ); } tot=t;}Code:
#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;struct Trie{ int node[520*64][256],fail[520*64],num[520*64]; int root,L; int newnode() { for(int i = 0;i < 256;i++) node[L][i] = -1; num[L] = -1; return L++; } void init() { L = 0; root = newnode(); } void insert(unsigned char buf[],int len,int id) { int now = root; for(int i = 0;i < len;i++) { if(node[now][buf[i]] == -1) node[now][buf[i]] = newnode(); now = node[now][buf[i]]; } num[now] = id; } void build() { queue<int>Q; fail[root] = root; for(int i = 0;i < 256;i++) if(node[root][i] == -1) node[root][i] = root; else { fail[node[root][i]]=root; Q.push(node[root][i]); } while(!Q.empty()) { int now = Q.front(); Q.pop(); for(int i = 0;i < 256;i++) if(node[now][i] == -1) node[now][i] = node[fail[now]][i]; else { fail[node[now][i]] = node[fail[now]][i]; Q.push(node[now][i]); } } } bool used[520]; int query(unsigned char buf[],int len,int n) { memset(used,false,sizeof(used)); int now = root; for(int i = 0;i < len;i++) { now = node[now][buf[i]]; int temp = now; while( temp!=root ) { if(num[temp] != -1) used[num[temp]]=true; temp = fail[temp]; } } int res = 0; for(int i = 0;i < n;i++) if(used[i]) res++; return res; }};unsigned char buf[2050];int tot;char str[4000];unsigned char s[4000];unsigned char Get(char ch){ if( ch>='A'&&ch<='Z' )return ch-'A'; if( ch>='a'&&ch<='z' )return ch-'a'+26; if( ch>='0'&&ch<='9' )return ch-'0'+52; if( ch=='+' )return 62; else return 63;}void change(unsigned char str[],int len){ int t=0; for(int i=0;i<len;i+=4) { buf[t++]=((str[i]<<2)|(str[i+1]>>4)); if(i+2 < len) buf[t++]=( (str[i+1]<<4)|(str[i+2]>>2) ); if(i+3 < len) buf[t++]= ( (str[i+2]<<6)|str[i+3] ); } tot=t;}Trie ac;int main(){ // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int n,m; while(scanf("%d",&n) == 1) { ac.init(); for(int i = 0;i < n;i++) { scanf("%s",str); int len = strlen(str); while(str[len-1]=='=')len--; for(int j = 0;j < len;j++) { s[j] = Get(str[j]); } change(s,len); ac.insert(buf,tot,i); } ac.build(); scanf("%d",&m); while(m--) { scanf("%s",str); int len=strlen(str); while(str[len-1]=='=')len--; for(int j = 0;j < len;j++) s[j] = Get(str[j]); change(s,len); printf("%d\n",ac.query(buf,tot,n)); } printf("\n"); } return 0;}
阅读全文
0 0
- [kuangbin带你飞]专题十七 AC自动机 D Detect the Virus
- [kuangbin带你飞]专题十七 AC自动机 C
- [kuangbin带你飞]专题十七 AC自动机 B 病毒侵袭
- ZOJ 3430 Detect the Virus AC自动机
- 【ZOJ】3430 Detect the Virus AC自动机
- Zoj 3430 Detect the Virus (AC自动机)
- zoj 3430 Detect the Virus(AC自动机)
- ZOJ 3430 Detect the Virus AC自动机
- zoj 3430 Detect the Virus AC自动机
- zoj 3430 Detect the Virus(ac自动机)
- ZOJ 3430 detect the virus AC自动机
- ZOJ 3430 Detect the Virus ac 自动机
- ZJU 3430 Detect the Virus AC自动机
- 【Ac自动机】Detect the Virus ZOJ
- [kuangbin带你飞]专题17:D
- ZOJ 3430 Detect the Virus(AC自动机+解码)
- ZOJ 3430 Detect the Virus 【AC自动机+解码】
- ZOJ 3430 Detect the Virus(AC自动机+字符串转换)
- mac如何启动一个thinkphp项目
- 统计不同时间段在线人数,给定若干(进入,离开)时间对
- java迭代器
- 左右括号全排列
- Codeforces Round #436 (Div. 2) A.Fair Game B.Polycarp and Letters C. Bus D.Make a Permutation!
- [kuangbin带你飞]专题十七 AC自动机 D Detect the Virus
- Linked List Cycle:判断链表是否有环
- 取消ssh,scp 询问
- Java 重写(Override)与重载(Overload)
- 渐变圆环进度条实现
- ARKit开发-简介及Demo展示
- Docker CE for Ubuntu安装笔记
- Delete Node In A LinkedList
- JZOJ 5385. 【NOIP2017提高A组模拟9.23】Carry