USACO最长前缀(trie练习题)
来源:互联网 发布:李刚疯狂java讲义 编辑:程序博客网 时间:2024/06/08 14:33
点我
题目描述
在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的。生物学家对于把长的序列分解成较短的序列(即元素)很感兴趣。
如果一个集合 P 中的元素可以通过串联(元素可以重复使用,相当于 Pascal 中的 “+” 运算符)组成一个序列 S ,那么我们认为序列 S 可以分解为 P 中的元素。元素不一定要全部出现(如下例中BBC就没有出现)。举个例子,序列 ABABACABAAB 可以分解为下面集合中的元素:
{A, AB, BA, CA, BBC}
序列 S 的前面 K 个字符称作 S 中长度为 K 的前缀。设计一个程序,输入一个元素集合以及一个大写字母序列 S ,设S'是序列S的最长前缀,使其可以分解为给出的集合P中的元素,求S'的长度K。
输入输出格式
输入格式:输入数据的开头包括 1..200 个元素(长度为 1..10 )组成的集合,用连续的以空格分开的字符串表示。字母全部是大写,数据可能不止一行。元素集合结束的标志是一个只包含一个 “.” 的行。集合中的元素没有重复。接着是大写字母序列 S ,长度为 1..200,000 ,用一行或者多行的字符串来表示,每行不超过 76 个字符。换行符并不是序列 S 的一部分。
输出格式:只有一行,输出一个整数,表示 S 符合条件的前缀的最大长度。
输入输出样例
输入样例#1:
A AB BA CA BBC.ABABACABAABC
输出样例#1:
11
说明
翻译来自NOCOW
USACO 2.3
代码
#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<ctime>#define For(i,a,b) for(register int i=a;i<=b;++i)#define Rep(i,a,b) for(register int i=a;i>=b;--i)const int maxx=1e5+7;using namespace std;int be[2000001],ne[2000001],to[2000001],e=0,cnt=0;void add(int x, int y){//链式前向星存trie to[++e]=y; ne[e]=be[x]; be[x]=e;}struct node{ bool end; char x;}llz[2000001];bool f[2000001];char x[1200],s[2000010];void insert(char *s){//trie的插入 int i,u=0,len=strlen(s); For(v,0,len-1){ bool flag=0; for(i=be[u];i;i=ne[i]){ int go=to[i]; if(llz[go].x==s[v]){ u=go; flag=1; break; } } if(!flag) {add(u,++cnt); u=cnt; llz[u].x=s[v];}// if(v==len-1) llz[u].end=1;//标记结束位置 }}bool find(int l,int r){//trie的查询 int i,u=0,flag; For(v,l,r){ flag=0; for(i=be[u];i;i=ne[i]){ int go=to[i]; if(llz[go].x==s[v]){ u=go; flag=1; break; } } if(!flag)return 0; if(v==r) if(llz[u].end==1){ return 1; } else return 0; }}int main(){#ifndef ONLINE_JUDGE freopen("input.in", "r", stdin); freopen("output.out", "w", stdout);#endif int i,j,l,ans=0,M=0; while(1){//对每个单词集合建trie scanf("%s",x); if(x[0]=='.') break;i=strlen(x);M=max(i,M);//找到最长的长度,下面会有用的 insert(x); } scanf("%s",s+1); while(scanf("%s",x)!=EOF) strcat(s+1,x);//读入s串 l=strlen(s+1); f[0]=1;//f[x]表示在x位置之前所有的字母能匹配 For(i,1,l){ for(j=i-1;j>=0;j--) if(f[j] && find(j+1,i)){//如果j以前能全部匹配,并且j+1到i能匹配,i位置也能全匹配 f[i]=1; ans=i; break; }if(j<0 && i-ans>M) break; //剪枝,如果当前比最长集合还要长的位置没匹配成功,后面也不能匹配上 } printf("%d\n",ans); return 0;}
code by 罗旅洲
阅读全文
0 0
- USACO最长前缀(trie练习题)
- usaco最长前缀(dp)
- USACO / Longest Prefix最长前缀(DP)
- USACO 最长前缀 Longest Prefix
- 最长前缀 [Codevs 2778][USACO]
- Trie树trie(前缀)
- Trie(前缀树)
- Trie(前缀树)
- USACO 2.3.1 Longest Prefix 最长前缀
- USACO:2.3.1 Longest Prefix 最长前缀
- usaco ★Longest Prefix 最长前缀
- usaco Cowxor (trie 树)
- JZOJ1266.【USACO题库】2.3.1 Longest Prefix最长前缀
- 最长公共前缀(LCP)
- Trie树(前缀树,字典树)
- Trie树(前缀树)的应用
- Trie (前缀树)uva 11732
- Poj 2001 (Trie 前缀树)
- 1864: [Zjoi2006]三色二叉树
- Python中布尔类型
- 8月23日小结
- 为什么不能通过返回值类型区分重载?
- 模板
- USACO最长前缀(trie练习题)
- 【Zookeeper】概述
- linux总结笔记(一)linux/ubuntu下ping www.baidu.com失败总结(校园网)
- [Leetcode] 365. Water and Jug Problem 解题报告
- 设计模式——单例模式(php)
- Flask实战2问答平台-父模板抽离(登录注册界面)
- 文本编辑部署servlet
- POJ2441-Arrange the Bulls
- Parcel_进程间数据传递