2007 Asia

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=282&page=show_problem&problem=1943

差点就被这个题目RE疯掉(ノへ ̄、)。

字典树:保存字符串集合。

用一个二维数组ch[i][j] 保存节点i,到标号j的叶子节点是否存在。一般val[i] 表示节点  i 对应的附加权值。

这个题目,给一个字典,一个文本,看文本可以有多少种分解方法。

用DP做,DP方程 dp[i] = sum(dp[i+len[x]]) ;   从后往前。

dp[i] 是从字符 i 开始的后缀数组的分解方案, x 是一个单词,是从 i 以后的单词

我RE的地方是ch数组用的char型,然后我一直查数组范围,LRJ的代码,我比照了好久O(≧口≦)O。

#include<cstring>
#include<vector>

using namespace std;

const int maxnode = 4000*100+10;
const int sigma_size = 26;

struct Trie
{
    int ch[maxnode][sigma_size];
    int val[maxnode];
    int sz;     ///节点总数
    void clear()
    {
        sz = 1;
        memset(ch[0],0,sizeof(ch[0]));
    }

    int idx(char c)
    {
        return c-'a';
    }

    void insert(const char *s, int v)
    {
        int u = 0, n = strlen(s);
        for(int i = 0; i < n; i++)
        {
            int c = idx(s[i]);
            if(!ch[u][c])   
            {
                memset(ch[sz], 0, sizeof(ch[sz]));
                val[sz] = 0;  
                ch[u][c] = sz++; 
            }
            u = ch[u][c]; 
        }
        val[u] = v; 
    }

    ///找字符串s不超过len的前缀
    void find_prefixes(const char *s, int len, vector<int>& ans)
    {
        int u = 0;
        for(int i = 0; i < len; i++)
        {
            if(s[i] == '') break;
            int c = idx(s[i]);
            if(!ch[u][c]) break;
            u = ch[u][c];
            if(val[u] != 0) ans.push_back(val[u]); // 找到一个前缀
        }
    }
};


#include<cstdio>
const int maxl = 300000+10;
const int maxw = 4000+10;
const int maxwl = 100+10;
const int MOD = 20071027;

int d[maxl],len[maxw];
char text[maxl],word[maxwl];
Trie trie;

int main()
{
    //freopen("in.txt","r",stdin);
    int cases =1 ;
    int s;
    while(scanf("%s%d",text,&s)==2)
    {
        trie.clear();
        for(int i=1; i<=s; i++)
        {
            scanf("%s",word);
            len[i] = strlen(word);
            trie.insert(word,i);
        }
        memset(d,0,sizeof(d));
        int L = strlen(text);
        d[L] = 1;
        for(int i=L-1; i>=0; i--)
        {
            vector<int> p;
            trie.find_prefixes(text+i,L-i,p);
            for(int j=0; j<p.size(); j++)
            {
                d[i] = (d[i]+d[i+len[p[j]]])%MOD;
            }
        }
        printf("Case %d: %d
",cases++,d[0]);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/TreeDream/p/5940245.html