Wannafly挑戰賽28 B msc和mcc DP
阿新 • • 發佈:2018-12-22
點我看題
解題思路:
很容易想到,合法的序列不是很多。
打個表發現只有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; }