C++:Hash字符串;回文字符串(hash+二分)

int范围内:进制数设置为107级别的素数(比如10000019或1e7+19),mod设置为109(1000000007或1e9+7)级别的素数,冲突概率最小。

stringHashToInt

long long hashstringtoInt(string str)
{
	//使用longlong是担心H中途溢出,但%后为int范围
	long long H = 0;
	for (int i = 0; i < str.size(); i++)
	{
		H = (H * P + str[i] - 'a') % MOD;
	}
	return H;
}

vector去重操作

int count = 0;
for (int i = 0; i < ans.size(); i++)
{
	if (i == 0 || ans[i] != ans[i - 1]) {
		count++;
	}
}

通过hashmap来找两个字符串最长匹配子串
关键点:
字符串[i…j]的hash值的计算:
H[i…j] = (H[j]-H[i-1]*P(j-i+1) )%MOD
为了避免H[i…j]可能为负值
H[i…j]=(H[i…j]+MOD)%MOD;

用powP存储每一次需要计算的P^(j-i+1)

变量定义以及powP初始化

#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int maxn = 1010;
const int P = 1e7 + 19;
const int MOD = 1e9 + 7;
LL powP[maxn], H1[maxn] = { 0 }, H2[maxn] = { 0 };
//        子串hash,子串长度
vector >pr1, pr2;

void PowerP(int len)
{
	powP[0] = 1;
	for (int i = 1; i <= len; i++)
	{
		powP[i] = (powP[i - 1] * P) % MOD;
	}
}

获取字符串哈希值

void getHash(string &str, LL H[])
{
	H[0] = str[0];
	for (int i = 1; i < str.size(); i++)
	{
		H[i] = (H[i - 1] * P + str[i]) % MOD;
	}
}

获取每一个子串的哈希值


int subHash(LL H[], int i, int j)
{
	if (i == 0)return H[j];//如果从0开始的子串 就是H[j]
	/*上面讲的求H[i...j]的关键:*/
	return ((H[j] - H[i - 1] * powP[j - i + 1]) % MOD + MOD) % MOD;
}
void getSubHash(int len, LL H[], vector >& pr)
{
	for (int i = 0; i < len; i++)
	{
		for (int j = i; j < len; j++)
		{
			int thisHash = subHash(H, i, j);
			pr.push_back(make_pair(thisHash, j - i + 1));
		}
	}
}

通过vector来判断第一个相同取,第二个最大。

int getMax()
{
	int maxl = 0;
	for (int i = 0; i < pr1.size(); i++)
	{
		for (int j = 0; j < pr2.size(); j++)
		{
			if (pr1[i].first == pr2[j].first) {
				maxl = max(maxl, pr1[i].second);
			}
		}
	}
	return maxl;
}

回文字符串

就是上方子串的扩展。回文中心点i,二分子串半径k

  • 如果回文串是奇数:本来应该和我后面那个ad比较,但可以用逆序,换成和逆序ad比较(hash值会相同)
    C++:Hash字符串;回文字符串(hash+二分)_第1张图片
  • 回文串为偶数:本来和后面的da比较,换成逆序ad比较(hash值会相同)
    C++:Hash字符串;回文字符串(hash+二分)_第2张图片

代码实现(没看懂)

#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int maxn = 1010;
const int P = 1e7 + 19;
const int MOD = 1e9 + 7;

LL powP[maxn], H[maxn] = { 0 }, reH[maxn] = { 0 };

void initpowP()
{
	powP[0] = 1;
	for (int i = 1; i mid;k仍在变大
	}
	return l - 1;
}
int main()
{
	string str;
	cin >> str;
	initpowP();
	getHash(str, H);
	reverse(str.begin(), str.end());
	getHash(str, reH);
	int ans = 0;

	//奇回文
	for (int i = 0; i < str.length(); i++)
	{
		//上界分界点:i的左右长度较小值+1
		int maxLen = min(i, (int)str.size() - i - 1) + 1;
		int k = binarySearch(0, maxLen, str.size(), i, 0);
		ans = max(ans, k * 2 + 1);
	}
	//偶回文
	for (int i = 0; i < str.length(); i++)
	{
		//二分上界分界点:i的左右长度较小值+1;(左长度:i+1)
		int maxlen = min(i + 1, (int)str.length() - i - 1) + 1;
		int k = binarySearch(0, maxlen, str.size(), i, 1);
		ans = max(ans, k * 2);
	}
	cout << ans;
}

你可能感兴趣的:(c++)