codeforces 123D

單調棧+後綴數組

此題看的角度是,先把後綴進行排序,然後每個後綴裏的子串,從前面開始數

比如aasss

其中一個後綴是

asss

那麼字串有

a as ass asss

明白了這個再想法用高度數組。

如果還不明白一般是不太會單調棧,建議去bzoj切幾道單調棧再回來看

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
char s[100010];
int bucket[210000], rankk[210000], pos[210000], y[210000],height[210000],x[210000];
struct valuee{
	int amount,len;
};
valuee value[1100000];
int top;
ll anss;
void getans(int len)
{
	top = 0; anss = 0;
	for (int i = 1; i <= len; i++)
	{
		int tempall = 0;
		while (top != 0 && value[top].len >=height[i])
		{
			ll realamount= value[top].amount+1;
			ll reallen = value[top].len - max(height[i],value[top-1].len);
			realamount = (realamount*(realamount + 1)) / 2;
			anss += realamount*reallen;
			if (value[top - 1].len >height[i])
				value[top - 1].amount += value[top].amount;
			else
				tempall += value[top].amount;
			top--;
		}
		if (height[i])
		{
			value[++top].len = height[i];
			value[top].amount= tempall+1;
		}
		else
		{
			value[0].len = 0; value[0].amount = 0;
		}
		int reallen = len - 1 - rankk[i]+1- max(height[i],height[i-1]);
		anss += reallen;
	}
}
void stringsort(int len)
{
	int templen = max(len, 26);
	for (int i = 0; i < len; i++)
	{
		bucket[s[i] - 'a' + 1]++;
	}
	for (int i = 1; i <=templen; i++)
		bucket[i] += bucket[i - 1];
	for (int i = 0; i < len; i++)
		rankk[bucket[s[i] - 'a' + 1]--] = i,
		pos[i]=s[i]-'a'+1;
	for (int i = 1;i<=templen; i++)
		bucket[i] = 0;
	for (int i = 1; i <=len; i<<=1)//
	{
		int m = 0;
		for (int j = len-1; j >len-1- i; j--)
			y[m++] = j;
		for (int j = 1; j <=len; j++)
		{
			if (rankk[j] <= i - 1 )
				continue;
			y[m++] = rankk[j] - i;
		}
		for (int j = 0; j < len; j++)
			bucket[pos[j]]++;
		for (int j = 1; j <= templen; j++)
			bucket[j] += bucket[j - 1];
		for (int j = 0; j < len; j++)
			x[j] = pos[j];
		for (int j = m-1; j>=0; j--)
		{
			int realrank = x[y[j]];
			rankk[bucket[realrank]--] = y[j];
		}
		for (int j= 0; j <= templen; j++)
			bucket[j] = 0;
		int level = 1;
		pos[rankk[1]] = 1;
		for (int j = 2; j <= len; j++)
		{
			int pos1 = rankk[j]; int pos2 = rankk[j - 1];
			int pos3 = pos1 + i; int pos4 = pos2 + i;
			if (x[pos1]>x[pos2])
			{
				pos[pos1] = ++level;
			}
			else
			{
				if (x[pos3] > x[pos4])
					pos[pos1] = ++level;
				else
					pos[pos1] = level;
			}
		}
	}
	for (int i = 0; i < len; i++)
		rankk[pos[i]] = i;
}
void getheight(int len)
{
	int h = 0;
	for (int i = 0; i < len; i++)
	{
		if (h)
			h--;
		int rank1 = pos[i]; int rank2 = rank1 + 1;
		int pos2 = rankk[rank2];
		while (s[i + h] == s[pos2 + h]&&rank1!=len)
			h++;
		if (rank1 != len)
			height[rank1] = h;
		else
			height[rank1] = 0;
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章