zoukankan      html  css  js  c++  java
  • SRM708 div1 PalindromicSubseq(动态规划+容斥原理)

    题目大意:给定一个字符串,记X[i]为包含s[i]这个字符的所有子列是回文串的个数(注意是子列而不是子串),求出所有的X[i]*(i+1),然后异或起来作为返回结果

    题解:

    首先用容斥来想,如果当前枚举到i

    那么答案就是

    1、选i作为中间的字幕,(0, i-1)和(i+1, L)这两个区间相互匹配回文

    2、直接选(0, i),(i+1, L)这两个区间相互匹配回文

    3、直接选(0, i-1), (i, L)这两个区间相互回文匹配

    然后我们发现后两种情况会有重叠情况

    我们把这两种情况更细致的分一下,(0, i), (i+1,L)如果能匹配,那么必定要找到s[j] = s[i], j是属于(i+1, L)的

    然后我们这样来做

    令f[l][r]表示, 只用(l, r)区间就可以构成回文串的个数

    令g[l][r]表示,用(0, l), (r, L)2个区间相互回文匹配构成的个数

    然后没找到一对(i, j),乘一下f[i+1][j-1], g[i-1][j+1]即可

    转移:

    f[l][r] = f[l+1][r] + f[l][r-1] - (s[l] == s[r] ? 0 : f[l+1][r-1])

    g[l][r] = g[l-1][r] + g[l][r+1] - (s[l] == s[r] ? 0 : s[l-1][r+1])

    然后就可以做了

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <sstream>
    #include <typeinfo>
    #include <fstream>
    
    using namespace std;
    typedef long long LL;
    const int maxn = 3050;
    const int MOD = 1e9 + 7;
    LL F[maxn][maxn], G[maxn][maxn];
    string S;
    LL g(int l, int r){
        if(l < 0 || r >= S.length()) return 1;
        if(G[l][r]) return G[l][r];
        G[l][r] = ((LL)g(l-1, r) + g(l, r+1) - (S[l] == S[r] ? 0 : g(l-1, r+1)))%MOD;
        return G[l][r];
    }
    
    LL f(int l, int r){
        if(l > r) return 1;
        if(l == r) return 2;
        if(F[l][r]) return F[l][r];
        F[l][r] = ((LL)f(l+1, r) + f(l, r-1) - (S[l] == S[r] ? 0 : f(l+1, r-1)))%MOD;
        return F[l][r];
    }
    
    class PalindromicSubseq {
        public:
        int solve(string s) {
            memset(F, 0, sizeof(F));
            memset(G, 0, sizeof(G));
            S = s;
            LL ans = 0;
            for(int i = 0; i < s.length(); i++){
                LL temp = 0;
                for(int j = 0; j < s.length(); j++)
                if(s[i] == s[j]){
                   int l = min(i, j), r = max(i, j);
                   (temp += (LL)f(l+1, r-1)*g(l-1, r+1)%MOD) %= MOD;
                }
                (temp += MOD) %= MOD;
                (temp *= (LL)(i+1)) %= MOD;
                ans ^= temp;
            }
            return ans;
        }
    };
  • 相关阅读:
    Selector + 线程池 遇到的问题
    【转】Android TabActivity无法正常bindService解决方法
    Android 中的 Service 全面总结
    【转】IT 圈里有哪些经常被读错的词?
    【转】线程的7种状态及相互转换
    【eoeandroid 特刊】第117期打包网盘下载地址
    使用 Android 自带的 proguard 混淆源码
    Google+ 连接不上的解决办法
    【转】AsyncTask的用法
    winForm简单数据绑定
  • 原文地址:https://www.cnblogs.com/Saurus/p/7103686.html
Copyright © 2011-2022 走看看