HDU 5763 Another Meaning

HDU 5763 Another Meaning

题意:一个字串有可能在模式串出现多次,问有多少种可能出现的情况。关键是有重合的字串是不能同时计入的。

思路:先用kmp求出所有字串的位置。然后,dp.

二维的时候:dp[i][j] i表示前i个子串,j的值1表示一定用这个串,0表示不用。值表示字串出现的情况数。

一维的时候可以直接用dp[i] 表示前i个字串能出现的情况。

然后,状态转移就都是分为三种情况:

1)当前子串和前一个子串不冲突,dp[i] = dp[i-1] * 2. 或者 dp[i][0] = dp[i-1][1] + dp[i-1][0] = dp[i][1] = dp[i-1][1].

2) 当前子串和前一个冲突,那就不一定是只和前一个冲突,所以从i-2开始寻找直到找到不冲突的j,有 dp[i] = dp[i-1] + dp[j]. 或者  dp[i][0] = dp[i-1][1] + dp[i-1][0] , dp[i][1] = dp[j][0] + dp[j][1].

3) 当前子串没找到上述的j子串,那么dp[i] = dp[i-1] + 1. 或者 dp[i][1] = 1.

二维代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;
const int mod=1000000007;
vector <int> ans;

vector <int> find_substring(string pattern, string text) {
    int n = pattern.size();
    vector <int> nxt(n+1, 0);
    for (int i=1; i<n; ++i) {
        int j = i;
        while(j > 0) {
            j = nxt[j];
            if (pattern[j] == pattern[i]) {
                nxt[i+1] = j + 1;
                break;
            }
        }
    }

    vector <int> positions;
    int m = text.size();
    for (int i=0, j=0; i<m; ++i) {
        if (j<n && text[i] == pattern[j]) {
            j++;
        }else {
            while (j>0) {
                j = nxt[j];
                if (text[i] == pattern[j]) {
                    j++;
                    break;
                }
            }
        }
         if (j == n) {
             positions.push_back(i-n+1);
        }
    }
    return positions;
}

int dp[100005][2]; // dp[i][1] 表示前i个串一定用上第i个时 maxans  dp[i][0] 表示前i个串的时候不用第i个时候的ans.

int main() {
    int t;
    //freopen("in.cpp", "r", stdin);
    cin >> t;
    string str1, str2;
    int cas = 0;
    while(t--) {
        ans.clear();
        cin >> str1 >> str2;
        ans = find_substring(str2, str1);
        int tot = ans.size();
        if (tot == 0) {
            printf("Case #%d: %d\n", ++cas, 1);
            continue;
        }

        dp[0][0] = 1;
        dp[0][1] = 1;

        for (int i=1; i<tot; ++i) {
            dp[i][0] = ((dp[i-1][0]%mod) + (dp[i-1][1]%mod))%mod;
            bool flag = false;
            for (int j=i-1; j>=0; --j) {
                if (ans[i] - ans[j] >= str2.length()) {
                    dp[i][1] = ((dp[j][1]%mod) + (dp[j][0]%mod)) % mod;
                    flag = true;
                    break;
                }
            }

           if (flag == false) {
              dp[i][1] = 1;
            }
            }
           // if(ans[i]-ans[i-1]>=str2.length())dp[i][1]=(dp[i][1]%mod+dp[i-1][1]%mod)%mod;
           printf("Case #%d: %d\n", ++cas, ((dp[tot-1][1]%mod)+(dp[tot-1][0]%mod))%mod);
        }
    return 0;
}

一维代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;
const int mod=1000000007;
vector <int> ans;

vector <int> find_substring(string pattern, string text) {
    int n = pattern.size();
    vector <int> nxt(n+1, 0);
    for (int i=1; i<n; ++i) {
        int j = i;
        while(j > 0) {
            j = nxt[j];
            if (pattern[j] == pattern[i]) {
                nxt[i+1] = j + 1;
                break;
            }
        }
    }

    vector <int> positions;
    int m = text.size();
    for (int i=0, j=0; i<m; ++i) {
        if (j<n && text[i] == pattern[j]) {
            j++;
        }else {
            while (j>0) {
                j = nxt[j];
                if (text[i] == pattern[j]) {
                    j++;
                    break;
                }
            }
        }
         if (j == n) {
             positions.push_back(i-n+1);
        }
    }
    return positions;
}

int dp[100005];

int main() {
    int t;
    //freopen("in.cpp", "r", stdin);
    cin >> t;
    string str1, str2;
    int cas = 0;
    while(t--) {
        ans.clear();
        cin >> str1 >> str2;
        ans = find_substring(str2, str1);
        int tot = ans.size();
        if (tot == 0) {
            printf("Case #%d: %d\n", ++cas, 1);
            continue;
        }

        dp[0] = 2;
        for (int i=1; i<tot; ++i) {
            if (ans[i]-ans[i-1]>=str2.length()) {
                dp[i] = (dp[i-1]*2)%mod;
            }
            else {
                bool flag = true;
                for (int j=i-2; j>=0; --j) {
                    if (ans[i] - ans[j] >= str2.length()) {
                        dp[i] = (dp[j] + dp[i-1])%mod;
                        flag = false;
                        break;
                    }
                }
                if (flag) dp[i] = (dp[i-1] + 1)%mod;
            }
        }

        printf("Case #%d: %d\n", ++cas, dp[tot-1]%mod);
    }
    return 0;
}

体验:dp无处不在..dp大法好... >_<

时间: 2024-08-02 11:03:18

HDU 5763 Another Meaning的相关文章

HDU 5763 Another Meaning(FFT)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5763 [题目大意] 给出两个串S和T,可以将S串中出现的T替换为*,问S串有几种表达方式. [题解] 我们定义数组f为S串中T出现的最后一个字母所在的位置,那么ans[i]=ans[i-1]+f[i-1]?ans[i-lenT]:0,一遍递推即可,所以关键就在于求出f数组了,f数组可以用kmp求,由于最近练FFT,用FFT求距离卷积匹配为0的位置,就是f数组了. [代码] #include <c

【动态规划】【KMP】HDU 5763 Another Meaning

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5763 题目大意: T组数据,给两个字符串s1,s2(len<=100000),s2可以被解读成2种意思,问s1可以解读成几种意思(mod 1000000007). 题目思路: [动态规划][KMP] 题目有点绕,看看样例就懂了.其实不用KMP直接用substr就能做. 首先不解读成另一个意思的话,f[i]=f[i-1],接着如果当前位置能够与s2匹配,那么f[i]+=f[i-strlen(s2)]

HDU 5763 Another Meaning(DP+KMP)

http://acm.hdu.edu.cn/showproblem.php?pid=5763 题意: 给出一个字符串和一个模式串,模式串有两种意思,问这句话有几种意思. 思路:因为肯定要去字符串去找模式串,所以首先用KMP计算next数组,然后用动态规划,d[i]表示分析到第i个字符时有多少种意思. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio>

hdu 5763 Another Meaning 哈希+dp

Another Meaning Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 917    Accepted Submission(s): 434 Problem Description As is known to all, in many cases, a word has two meanings. Such as “hehe”,

HDU 5763 Another Meaning dp+字符串hash

题意:给定一个句子str,和一个单词sub,这个单词sub可以翻译成两种不同的意思,问这个句子一共能翻译成多少种不能的意思 例如:str:hehehe   sub:hehe 那么,有**he.he**.和hehehe三种不同的意思, 考虑一下aaadaaa这种情况?sub:aa  前面的aaa有三种,后面的aaa有三种,所以一共应该是有9种情况. 可以考虑成3*3=9 如果你考虑分块去相乘的话,那么恭喜你,你GG了.因为这样写非常复杂,而且非常难判断. 可以考虑下dp,因为注意到,它每个单词只有

hdu 5763 Another Meaning (KMP/哈希+DP)

题目大意:给你两个串,一长一短,如果长串中某个子串和短串完全相同,则这个子串可以被替换成"#",求长串所有的表达形式....... 比如"hehehehe"和"hehe",则有5种情况,"#hehe","he#he","hehe#","##","hehehehe" 首先我们KMP/哈希找出长串中所有可以作为和短串结尾匹配成功后的位置 然后可以得到方

DP &#215; KMP

几道用到KMP的DP题: hdu 5763    hdu 3689    hdu 3336    codeforces 494B    codevs 3945 一道一道来~ hdu 5763  Another Meaning 题意及样例:原题链接 设第一个串为A,长为n:第二个串为B,长为L 从1到n计算1~k能代表的意思的数量f[k] 如果A[k-L+1,k]==B 则f[k]=f[k-L]+f[k-1] 否则f[k]=f[k-1] 判断A[k-L+1,k]是否与B匹配就要靠KMP了 1 #i

HDU 3296 &amp; POJ 3138 Acm Team Section(数学)

题目链接: HDU: http://acm.hdu.edu.cn/showproblem.php?pid=3296 POJ:  http://poj.org/problem?id=3138 Acm Team Section Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 159    Accepted Submission(s): 47

LCA(最近公共祖先)--tarjan离线算法 hdu 2586

HDU 2586 How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11320    Accepted Submission(s): 4119 Problem Description There are n houses in the village and some bidirectional roads c