随机三模数哈希

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<bitset>
#include<ctime>
using namespace std;
///////////////////////////////////////////////////////sjkkkiqnsnknans
///////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans

#define f(i ,m ,n ,x) for (int i = (m) ; i <= (n) ; i += (x))
typedef long long ll ;
double BEGIN,END;
template <typename T>
inline T Max(T x,T y) {
	return (x > y ? x : y);
}
template <typename T>
inline T Min(T x,T y) {
	return (x < y ? x : y);
}
template <typename T>
inline T Abs(T x) {
	return (x < 0 ? ~x+1 : x);
}
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans

const int N = 1e6 + 7 ;
const ll p = 998244353ll ,base = 131ll ;
const ll up = 2e9 ;
char s[N] ,t[N] ;
ll ls ,lt ,loc[N] ,dp[N] ,g[N] ,ans[N] ,c[N] ,cnt ;
ll pr[150] = {0ll ,899997011ll ,899997019ll ,899997029ll ,899997041ll ,899997047ll ,899997089ll ,899997097ll ,
              899997113ll ,899997167ll ,899997173ll ,899997179ll ,899997229ll ,899997247ll ,899997271ll ,899997283ll ,899997317ll ,
              899997359ll ,899997401ll ,899997419ll ,899997421ll ,899997451ll ,899997463ll ,899997473ll ,899997479ll ,899997499ll ,
              899997503ll ,899997523ll ,899997559ll ,899997587ll ,899997589ll ,899997619ll ,899997661ll ,899997671ll ,899997677ll ,
              899997701ll ,899997737ll ,899997739ll ,899997743ll ,899997773ll ,899997779ll ,899997781ll ,899997827ll ,899997841ll ,
              899997863ll ,899997883ll ,899997887ll 
			  /*////////////////////////////////////////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
//sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
*/
			  
			  
			  ,899997911ll ,899997949ll ,899997961ll ,899997991ll ,899998013ll ,899998019ll ,
              899998049ll ,899998051ll ,899998063ll ,899998097ll ,899998103ll ,899998109ll ,899998117ll ,899998157ll ,899998163ll ,
              899998181ll ,899998193ll ,899998271ll ,899998273ll ,899998313ll ,899998367ll ,899998373ll ,899998387ll ,899998391ll ,
              899998399ll ,899998409ll ,899998439ll ,899998457ll ,899998481ll ,899998501ll ,899998523ll ,899998537ll ,899998553ll ,
              899998559ll ,899998597ll ,899998601ll ,899998607ll ,899998613ll ,899998639ll ,899998661ll ,899998663ll ,899998679ll ,
              899998691ll ,899998709ll ,899998733ll ,899998753ll ,899998811ll ,899998843ll ,899998861ll ,899998909ll ,899998919ll ,
              899998927ll ,899998937ll ,899998961ll ,899999003ll ,899999029ll ,899999033ll ,899999041ll ,899999069ll ,899999071ll ,
              899999119ll ,899999123ll ,899999143ll ,899999167ll ,899999173ll ,899999197ll ,899999231ll ,899999281ll ,899999299ll ,
              899999333ll ,899999341ll ,899999357ll ,899999371ll ,899999389ll ,899999423ll ,899999437ll ,899999483ll ,899999531ll ,
              899999537ll ,899999539ll ,899999549ll ,899999557ll ,899999609ll ,899999701ll ,899999741ll ,899999743ll ,899999759ll ,
              899999777ll ,899999797ll ,899999801ll ,899999813ll ,899999911ll ,899999921ll ,899999929ll ,899999963ll
             } ;

/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans

inline int myrand (int l ,int r) {
	return std :: rand () % (r - l + 1) + l ;
}

class good_hash {
	
	private :
		ll mod ,hs[N] ,ht[N] ,pw[N] ,qp[30] ;
		std :: bitset < 900000000 > se ;
		inline ll hash (int l ,int r) {
			return (hs[r] - hs[l - 1] * pw[r - l + 1] % mod + mod)%mod;
		}

		inline ll qpow (ll base) {
			ll p = mod - 2ll ,res = 1ll ;
			while (p) {
				if (p & 1ll){
					res *= base ;
					res>= mod ? res%=mod : 0;
				}
				base *= base ;
				base >= mod ? base%=mod : 0;
				p >>= 1ll ;
			}
			return res ;
		}

	public :
		inline void pre () {
//			BEGIN = clock();
			mod = pr[myrand (1 ,141)] ;
			f (i ,1 ,ls ,1){
				hs[i] = (hs[i - 1] * base % mod + s[i]);
				hs[i] >= mod ? hs[i]%=mod : 0;
			}
			
			f (i ,1 ,lt ,1){
				ht[i] = (ht[i - 1] * base % mod + t[i]);
				ht[i] >= mod ? ht[i]%=mod : 0;
			}

			pw[0] = 1ll ;
			se[1] = 1 ;
			f (i ,1 ,std :: max (ls ,lt) ,1) {
				pw[i] = pw[i - 1] * base ;
				pw[i] >= mod ? pw[i]%=mod : 0;
				se[pw[i]] = 1 ;
			}

			f (i ,1 ,25 ,1)
			qp[i] = qpow (i) ;
//			END = clock();
//			std :: cout << (END-BEGIN)/1000.0 <<"s" ; putchar('\n');
		}

		inline int judge (int l ,int r) {
			int len = r - l + 1 ;
			ll ha = hash (l ,r) ;
			if (ha == ht[len]) return 1 ;

			ll ha_ = ha ;
			ha = (ha - ht[len] + mod) % mod ;
			f (i ,1 ,25 ,1)
			if (se[ha * qp[i] % mod] == 1) return 1 ;
			ha = (ht[len] - ha_ + mod) % mod ;
			f (i ,1 ,25 ,1)
			if (se[ha * qp[i] % mod] == 1) return 1 ;
			return 0 ;
		}
} h1 ,h2 ,h3  ;

inline int judge (int l ,int r) {
	//return h1.judge (l ,r) ;
	return h1.judge (l ,r) && h2.judge (l ,r) && h3.judge (l ,r) ;
}
int main () {

	std :: ios :: sync_with_stdio (0) ;
	std :: cin.tie (nullptr) ;
	std :: cout.tie (nullptr) ;
	std :: srand (std :: time (0)) ;

	scanf("%s",s+1);scanf("%s",t+1); 
	/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans
/////////////////////////////////////sjkkkiqnsnknans

	ls = std :: strlen (s + 1) ,lt = std :: strlen (t + 1) ;
	h1.pre () ,h2.pre () ,h3.pre () ;
	
	BEGIN = clock();
	int l = 1 ,r = Min (lt ,ls) ,res ;
	//if (judge (1 ,r)) { res = r ; goto her ;}
	
	while (l <= r) {
		int mid = l + r >> 1 ;
		if (judge (1 ,mid)) {
			l = mid + 1 ,res = mid ;
			//if (! judge (1 ,mid + 1)) break ;
		} else r = mid - 1 ;
	} //her : ;
	
	END = clock();
	cout << (END-BEGIN)/1000.0 << "s" << endl;
	BEGIN = clock();
	c[1] ++ ;
	c[res + 1] = p - 1 ;
	int cur = 1 ;
	ll tot = 0ll ;
	loc[1] = res ;
	f (i ,1 ,ls - 1 ,1) {
		while (cur <= i) {
			tot += c[cur ++] ;
		//	while (tot < 0) tot += p ;
			if (tot >= p) tot %= p ;
		}
		dp[i] = tot ;
		int l = i + 1 ,r = Min (ls ,i + lt) ,res ;
		//  if (judge (i + 1 ,r)) { res = r ; goto her_ ;}
		while (l <= r) {
			int mid = l + r >> 1 ;
			if (judge (i + 1 ,mid)) {
				l = mid + 1 ,res = mid ;
				//if (! judge (i + 1 ,mid + 1)) break ;
			} else r = mid - 1 ;
		} //her_ : ;
		loc[i + 1] = res ;
		//std :: cout << i + 1 << ' ' << res << '\n' ;
		(c[i + 1] += dp[i]) ;
		//while (c[i + 1] < 0) c[i + 1] += p ;
		if (c[i + 1] >= p) c[i + 1] %= p ;
		(c[loc[i + 1] + 1] += p - dp[i]) ;
		if (c[loc[i + 1] + 1] >= p) c[loc[i + 1] + 1] %= p ;
	} (tot += c[cur] + p) ;
	if (tot >= p) tot %= p ;
	dp[ls] = tot ;
	END = clock();
	cout << (END-BEGIN)/1000.0 << "s" << endl;
	
	//puts ("111111") ;

	memset (c ,0 ,sizeof c) ;
	c[1] ++ ;
	c[loc[1] + 1] = p - 1 ;
	cur = 1 ;
	tot = 0ll ;
	f (i ,1 ,ls - 1 ,1) {
		while (cur <= i) (tot += c[cur ++] + p) %= p ;
		g[i] = tot ;
		(c[i + 1] += dp[i] + g[i] + p) %= p ;
		(c[loc[i + 1] + 1] += (p << 1) - dp[i] - g[i]) %= p ;
	} (tot += c[cur] + p) %= p ;
	g[ls] = tot ;

	memset (c ,0 ,sizeof c) ;
	c[1] ++ ;
	c[loc[1] + 1] = p - 1 ;
	cur = 1 ,tot = 0ll ;
	f (i ,1 ,ls - 1 ,1) {
		while (cur <= i) (tot += c[cur ++] + p) %= p ;
		ans[i] = tot ;
		(c[i + 1] += dp[i] + ans[i] + (g[i] << 1) + p) %= p ;
		(c[loc[i + 1] + 1] += (p << 2) - dp[i] - ans[i] - (g[i] << 1)) %= p ;
	} (tot += c[cur] + p) %= p ;
	ans[ls] = tot ;
	std :: cout << ans[ls] << '\n' ;
	return 0 ;
}

posted @ 2024-12-19 08:18  Tmbcan  阅读(5)  评论(0编辑  收藏  举报