2010辽宁省赛F(字典树,动态规划)

#include<bits/stdc++.h>
using namespace std;
int n,x;
char s[10010];
char a[31010];
int val[100010];
int ch[100010][30];
int dp[100010];
int main()
{
    while(~scanf("%d",&n))
    {
        scanf("%s",s+1);
        int len=strlen(s+1);
        memset(ch[0],0,sizeof(ch[0]));
        int cnt=0;//记录编号
        for(int i=1;i<=n;i++)
        {
            int u=0;//父节点,0为根节点
            scanf("%s%d",a,&x);
            for(int j=0;j<strlen(a);j++)
            {
                if(!ch[u][a[j]-'a'])//字典树中该位置已存在该字母
                {
                    ch[u][a[j]-'a']=++cnt;
                    memset(ch[cnt],0,sizeof(ch[cnt]));
                    val[cnt]=0;
                }
                u=ch[u][a[j]-'a'];
            }
            val[u]=max(val[u],x);//u为结尾结点的编号,val[u]表示该串的权重
        }
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(int i=1;i<=len;i++)
        {
            int u=0;
            if(!dp[i-1])
                continue;
            for(int j=i;j<=i+30&&j<=len;j++)
            {
                if(ch[u][s[j]-'a'])
                {
                    u=ch[u][s[j]-'a'];
                    if(val[u])//如果有以u结尾的字符串,检验它的权重加上i结束的字符串的权重是否比原来更大
                        dp[j]=max(dp[j],dp[i-1]+val[u]);
                }
                else
                    break;
            }
        }
    //模拟从开始到完成字符串加入进行匹配的过程
        printf("%d\n",dp[len]-1);
    }
    return 0;
}
//字典树是一种以空间换时间的数据结构,在ch数组中,第一维表示父节点,第二维表示兄弟节点。每个节点挂一个链表,把它后面的节点连起来,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数。
posted @ 2018-08-04 08:59  sewage  阅读(148)  评论(0编辑  收藏  举报