1. 程式人生 > >Wannafly挑戰賽28 B msc和mcc DP

Wannafly挑戰賽28 B msc和mcc DP

點我看題
解題思路:
很容易想到,合法的序列不是很多。
打個表發現只有8個。
定義dp[i][j] 表示從第i位開始 第一次出現標號為j的字元的位置是什麼。 美名曰 序列自動機
然後暴力匹配八個串,列舉所有的(x,y) 最後再大力去重就可以了。
(遇到了寫蜜(shu)汁(zu)bug(yue jie))

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef unsigned long long  ULL;
typedef long long LL;
string str1,str2;
const int MAX=  1e5+10;
set<string> S;
int now = 0;
void dfs(int d1,int d2,string str) {
    now++;
    if(d1==3 && d2==3) {
        S.insert(str);
        return;
    }
    if(d1<3) {
        dfs(d1+1,d2,str+str1[d1]);
    }
    if(d2<3) {
        dfs(d1,d2+1,str+str2[d2]);
    }
}
vector<string> V;
vector<pair<int,int> > P;
char str[MAX];
char ID[300];
int id(char x) {
    return ID[x];
}
LL n;
int nexts[MAX][3];
void init() {
    ID['m']=0;
    ID['c']=1;
    ID['s']=2;
    memset(nexts,-1,sizeof nexts);
    str1="msc";
    str2="mcc";
    dfs(0,0,string());
    for(string u:S) {
        V.push_back(u);
    }
    for(int i=n-1; i>=0; i--) {
        for(int j=0; j<3 && i>0; j++) nexts[i-1][j]=nexts[i][j];
        nexts[i-1][id(str[i])]=i;
    }
}
int getend(string &s,int pos){
    for(int i=1;i<6;i++){
        pos=nexts[pos][id(s[i])];
        if(pos==-1) return -1;
    }
    return pos;
}
void slove() {
    for(int i=0;i<n;i++){
        for(int j=0;j<V.size();j++){
            int l;
            if(V[j][0]==str[i]){
                l=i;
            }else{
                l=nexts[i][id(V[j][0])];
            }
            int r=getend(V[j],l);
            if(l==-1 || r==-1) continue;
            P.push_back(make_pair(l,r));
        }
    }
    sort(P.begin(),P.end());
    long long ans = 0;
    LL l=-1, r=n;
    for(auto &u:P){
        LL nowl=u.first;
        LL nowr=u.second;
        LL newl=max(0ll,nowl-l);
        LL newr=max(0ll,r-nowr);
        l=max(nowl,l);
        r=min(r,nowr);
        ans += ((nowl+1)*newr)+((n-nowr)*(newl));
        ans -= (newl*newr);
    }
    cout<<ans<<endl;
}
int main() {
    scanf("%lld",&n);
    scanf("%s",str);
    init();
    slove();
    return 0;
}