Hatena::Grouptopcoder

kojingharangの日記 RSSフィード

 | 

2012-02-25

C. Hometask

12:09 |  C. Hometask - kojingharangの日記 を含むブックマーク はてなブックマーク -  C. Hometask - kojingharangの日記  C. Hometask - kojingharangの日記 のブックマークコメント

文字列Sと、隣り合ってはいけない2つの文字(Ai,Bi)が何セットか与えられる。各Ai,Biで同じ文字は1回しか出てこない。

Sから最低何文字消せばいいか。

禁止文字が高々1回なので、ある (Ai,Bi) に関する制約を満たす操作をした後に新たに別の制約が破られるようにはならない。

たとえば (a,b)が禁止という条件で (ab以外) aかbの並び (ab以外) を処理する場合、(?,a), (?,b)という禁止セットはないことがわかっているので、

aかbの並びからどういう消し方をしても (ab以外)とaまたはbが隣接することになるので、この部分に関してはほかの条件を満たしている。

ということで連鎖しないことがわかったので、禁止文字セットは1回ずつ処理するだけでいい。

(ab以外) aかbの並び (ab以外) を処理するには、aかbの並びを全てaかbにするしかないので、aとbで文字数の少ない方を消せばいい。(実際には消さないで数えるだけでOK)

というわけで O(Sの長さ*制約の数) で処理できる。

int main() {
	string s;
	cin>>s;
	int N;
	cin>>N;
	int ans=0;
	REP(i, N) {
		string ng;
		cin>>ng;
		char a=ng[0];
		char b=ng[1];
		
		REP(i, s.size()) {
			int ca=0, cb=0;
			for(;i<s.size();i++) {
				if(s[i]!=a && s[i]!=b) break;
				ca+=s[i]==a;
				cb+=s[i]==b;
			}
			ans += min(ca, cb);
		}
	}
	cout<<ans<<endl;
	
	return 0;
}
 |