关于哈希做法的求助
查看原帖
关于哈希做法的求助
800543
NirvanaCeleste楼主2024/10/11 17:27
#include <bits/stdc++.h>
using namespace std;
const int base = 133,maxn = 2000200;
#define ull unsigned long long
int n;
string s;
stack<char> b;
map<ull,int> m;//C(2,k) = k! / 2! * (k - 2)!
ull ans,h;
ull mhash[maxn];
typedef map<ull,int>::iterator pll;//声明迭代器iterator类型
int main(){
	cin>>n;
	cin>>s;
	s = ' ' + s;
	int dep = 0;
	for(int i=1;i<=n;i++){//O(n) 求出所有字串的合法方案数 枚举原理 哈希省略了左端点的枚举
		m[h]++;//在前面统计 因为有一个continue 
		char ch = s[i];
		if(b.empty()){
			b.push(ch);
			h = h * base + ch - 'a' + 1;//加1原因 非空串不为0
			mhash[i] = h;
			dep = 0;
			continue;
		}
		if(b.top() == ch){
			b.pop();
//			h = h - (ch - 'a' + 1) / base;
			dep++;
			h = mhash[i - dep*2];//检查一下是否如此:你空字符串的哈希值是0,单独一个a的哈希值也是0 如果是,改掉。
		}else{
			b.push(ch);
			h = h * base + ch - 'a' + 1;
			dep = 0;
		}
		mhash[i] = h;
	}
	m[h]++;
	for(pll it=m.begin();it!=m.end();it++){
		int k = it->second;//C(2,k) = k! / 2! * (k - 2)!
		if(k < 2) continue;
		else if(k == 2) ans++;
		else ans += (k - 1) * k / 2;
	}
	cout<<ans;
	return 0;
}

思路:形如 abbacddc 的字符串,一个子串可消除是一个回文串,所以引入deep描述连续出栈的次数,即可消除子串的一半长度

2024/10/11 17:27
加载中...