CF 346B. Lucky Common Subsequence(DP+KMP)
这题确实很棒。。又是无想法。。其实是AC自动机+DP的感觉,但是只有一个串,用kmp就行了。
dp[i][j][k],k代表前缀为virus[k]的状态,len表示其他所有状态串,处理出Ac[len][26]数组来,DP就可以了。状态转移那里一直没想清楚,wa了很多次,记录路径倒是不复杂,瞎搞搞就行。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
char s1[],s2[],virus[];
int dp[][][];
int pre[][][];
int pre1[][][];
int Ac[][];
int next[];
char ans[];
void kmp()
{
int i,j,len,temp;
len = strlen(virus);
next[] = -;
j = -;
for(i = ; i < len; i ++)
{
while(j >= &&virus[j+] != virus[i])
j = next[j];
if(virus[j+] == virus[i]) j ++;
next[i] = j;
}
for(i = ; i < len; i ++)
{
for(j = ; j < ; j ++)
{
temp = i;
while(temp >= &&virus[temp+] != 'A'+j)
temp = next[temp];
if(virus[temp+] == 'A' + j) temp ++;
if(temp == -)
Ac[i][j] = len;
else
Ac[i][j] = temp;
}
}
for(i = ; i < ; i ++)
{
if(i + 'A' == virus[])
Ac[len][i] = ;
else
Ac[len][i] = len;
}
}
int main()
{
int i,j,k,len1,len2,len,maxz,a,b,kk;
scanf("%s%s%s",s1,s2,virus);
len1 = strlen(s1);
len2 = strlen(s2);
len = strlen(virus);
kmp();
for(i = ; i <= len1; i ++)
{
for(j = ; j <= len2; j ++)
{
for(k = ; k <= len; k ++)
{
if(k == len-) continue;
if(dp[i][j][k] < dp[i-][j][k])
{
dp[i][j][k] = dp[i-][j][k];
pre[i][j][k] = ;
pre1[i][j][k] = k;
}
if(dp[i][j][k] < dp[i][j-][k])
{
dp[i][j][k] = dp[i][j-][k];
pre[i][j][k] = ;
pre1[i][j][k] = k;
}
if(s1[i-] == s2[j-])
{
if(Ac[k][s1[i-]-'A'] == len-) continue;
else if(dp[i][j][Ac[k][s1[i-]-'A']] < dp[i-][j-][k] + )
{
dp[i][j][Ac[k][s1[i-]-'A']] = dp[i-][j-][k] + ;
pre[i][j][Ac[k][s1[i-]-'A']] = ;
pre1[i][j][Ac[k][s1[i-]-'A']] = k;
}
}
}
}
}
maxz = ;
for(i = ; i <= len1; i ++)
{
for(j = ; j <= len2; j ++)
{
for(k = ; k <= len; k ++)
{
if(maxz < dp[i][j][k])
{
maxz = dp[i][j][k];
a = i;
b = j;
kk = k;
}
}
}
}
if(maxz == )
{
printf("0\n");
return ;
}
int num = ;
//printf("%d\n",maxz);
while(a != &&b != )
{
if(pre[a][b][kk] == )
{
ans[num++] = s1[a-];
kk = pre1[a][b][kk];
a --;
b --;
}
else if(pre[a][b][kk] == )
{
kk = pre1[a][b][kk];
a --;
}
else if(pre[a][b][kk] == )
{
kk = pre1[a][b][kk];
b --;
}
else
break;
}
for(i = num-; i >= ; i --)
{
printf("%c",ans[i]);
}
printf("\n");
return ;
}
CF 346B. Lucky Common Subsequence(DP+KMP)的更多相关文章
- Common Subsequence(dp)
Common Subsequence Time Limit: 2 Sec Memory Limit: 64 MBSubmit: 951 Solved: 374 Description A subs ...
- UVA 10405 Longest Common Subsequence (dp + LCS)
Problem C: Longest Common Subsequence Sequence 1: Sequence 2: Given two sequences of characters, pri ...
- POJ1458 Common Subsequence —— DP 最长公共子序列(LCS)
题目链接:http://poj.org/problem?id=1458 Common Subsequence Time Limit: 1000MS Memory Limit: 10000K Tot ...
- Codeforces Round#201(div1) D. Lucky Common Subsequence
题意:给定两个串,求出两个串的最长公共子序列,要求该公共子序列不包含virus串. 用dp+kmp实现 dp[i][j][k]表示以i结尾的字符串和以j结尾的字符串的公共子序列的长度(其中k表示该公共 ...
- POJ - 1458 Common Subsequence DP最长公共子序列(LCS)
Common Subsequence A subsequence of a given sequence is the given sequence with some elements (possi ...
- Longest Common Subsequence (DP)
Given two strings, find the longest common subsequence (LCS). Your code should return the length of ...
- HDU 1159 Common Subsequence --- DP入门之最长公共子序列
题目链接 基础的最长公共子序列 #include <bits/stdc++.h> using namespace std; ; char c[maxn],d[maxn]; int dp[m ...
- POJ 1458 Common Subsequence DP
http://poj.org/problem?id=1458 用dp[i][j]表示处理到第1个字符的第i个,第二个字符的第j个时的最长LCS. 1.如果str[i] == sub[j],那么LCS长 ...
- HDU 1159 Common Subsequence【dp+最长公共子序列】
Common Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
随机推荐
- Power BI for Office 365介绍
微软在七月份发布了一个新产品,它建立在微软的云的第一个数据平台- Power BI for Office 365.Satya Nadella,服务器和工具业务总裁,在当天的上午在微软的年度全球合作伙伴 ...
- POJ2762 Going from u to v or from v to u(单连通 缩点)
判断图是否单连通,先用强连通分图处理,再拓扑排序,需注意: 符合要求的不一定是链拓扑排序列结果唯一,即在队列中的元素始终只有一个 #include<cstdio> #include< ...
- <转>FreeMarker内置函数
一. Sequence的内置函数1. sequence?first 返回sequence的第一个值.2. sequence?last 返回sequence的最后一个值.3. sequence?reve ...
- .NET NLog 详解(五) - Condition Expression
Sample <!-- during normal execution only log Info messages --> <defaultFilter>level > ...
- 面试题之【打印1到最大的N位数】
题目描述:给定一个数字N,打印从1到最大的N位数. 看起来像是很简单的问题(虽然实际也不是很难...)我们很容易写出这样的代码: #include<iostream> #include&l ...
- Windows Phone中获取UserAgent
进入WP8时代后,通过DeviceExtendedProperties获取到的DeviceName不再是手机型号了,这对于需要获得手机型号做一些事情的应用(如新浪微博的小尾巴)来说,影响是比较大的. ...
- Iterator
hasNext() 方法是检查序列中是否还有元素. remove()方法是将迭代器返回的元素删除. List list = new ArrayList(); list .add(“a”); for(I ...
- Linux内核装载和启动一个可执行程序
“平安的祝福 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 理解编 ...
- POJ 3261 后缀数组
题目链接:http://poj.org/problem?id=3261 题意:约翰注意到奶牛产奶的之类是不断变化的,虽然他不能预测从当天到下一天的变化情况但是他知道变化是有规律的,牛奶的质量由一个整数 ...
- redis 的使用 (基础, key操作, string类型操作)
使用redis set 类型: 没有重复元素 list 链表类型 有重复累型 sort set 类型 没有重复元素 1.1 存储数据 读取数据 // 数据储存在 内存中 set name laowen ...