fzu2162 largeCommon

来源:互联网 发布:js点击显示div 编辑:程序博客网 时间:2024/06/13 12:17
 Problem 2162 largeCommon

Accept: 3    Submit: 46
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

给你2个字符串s1,s2。同时给n个不同字符串和每个的价值value。找出一个s1与s2的公共子序列价值最大,价值等于子序列中包含的子串的value的总和(仅计算给出的n)。

 Input

对于每组数据,先输入两个字符串s1,s2(1=<|s1|,|s2|<=100),然后一个整数n,然后输入n个字符串和价值value(-1000<=value<=1000)。并且n个串的长度总和小于等于100.所有字符的为小写。

 Output

输出最大的价值

 Sample Input

ababcababc
2
ababc -100
ab 10

 Sample Output

20

Submit  Back  Status

构建ac自动机, 
dp[i][j][k]表示 第一个字符串到i,第二个字符串到j,公共序列在自动机上到达k点时的最大value
 dp[i][j][ tree[k][c] ]= max( dp[i-1][j-1][k] + g[ tree[k][c] ] , dp[i][j][ tree[k][c] ]  )

#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;#define inf  (1<<30)char s1[111],s2[111],s[111];int tree[111][27];int f[111][111];int n,m,tot,ans,len1,len2;int g[111], p[111];int dp[111][111][111];int idx( char c){    return  c-'a';}int main(){    while (scanf("%s",s1+1)!=EOF)    {        scanf("%s",s2+1);        len1=strlen(s1+1), len2=strlen(s2+1);        memset(tree,0,sizeof(tree));        memset( g, 0 ,sizeof(g) );        memset( p, 0 ,sizeof(p) );        scanf("%d",&n);        tot=0;        for (int i=1; i<=n; i++)        {            int x;            scanf("%s%d",s,&x);            int len=strlen(s),u=0;            for (int j=0; j<len; j++)            {                int  c=idx(s[j]);                if ( !tree[u][c] )                    tree[u][c]=++tot;                u=tree[u][c];            }            g[u]=x;        }        queue <int> q;        for (int i=0; i<26; i++)            if (tree[0][i])                q.push(tree[0][i]);        while (!q.empty())        {            int r=q.front();            q.pop();            for (int i=0; i<26; i++)            {                int u=p[r];                while (  u && !tree[u][i] )  u=p[u];                int v= tree[r][i];                if ( v )                {                    q.push( v );                    p[ v ] = tree[u][i];                    g[ v ] +=  g[ p[v] ];                }                else                    tree[r][i]= tree[u][i];            }        }        for (int i=0; i<=len1; i++)            for (int j=0; j<=len2; j++)                for (int k=0; k<=tot ; k++)                    dp[i][j][k]=-inf;        for (int i=0; i<=len1; i++)            dp[i][0][0]=0;        for (int i=0; i<=len2; i++)            dp[0][i][0]=0;        for (int i=1; i<=len1; i++)            for (int j=1; j<=len2; j++)            {                for (int k=0; k<=tot; k++)                {                    dp[i][j][k]= max( dp[i][j][k], dp[i-1][j][k]) ;                    dp[i][j][k]= max( dp[i][j][k], dp[i][j-1][k]) ;                    dp[i][j][k]= max( dp[i][j][k], dp[i-1][j-1][k]) ;                }                if (s1[i]==s2[j])                {                    int c= idx(s1[i]);                    for (int k=0; k<=tot; k++)                        if(dp[i-1][j-1][k]>-inf )                        dp[i][j][ tree[k][c] ]= max( dp[i-1][j-1][k] + g[ tree[k][c] ] , dp[i][j][ tree[k][c] ]  );                }            }        ans= 0;        for (int i=0; i<=tot ;i++)            ans= max( ans , dp[len1][len2][i]);        printf("%d\n",ans);    }    return 0;}



0 0
原创粉丝点击