52 分求调
查看原帖
52 分求调
363006
wangyibo201026楼主2024/4/14 19:42

做法具体而言,把所有字符串转化为带通配符的,然后把 tt 全部插进 ACAM 里,然后 ss 再一个个查:

#include <bits/stdc++.h>

using namespace std;

#define int long long
#define fir first
#define sec second
#define mkp make_pair 
#define pb push_back
#define lep( i, l, r ) for ( int i = ( l ); i <= ( r ); ++ i )
#define rep( i, r, l ) for ( int i = ( r ); i >= ( l ); -- i )

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
typedef pair < int, int > pii;

char _c; bool _f; template < class type > inline void read ( type &x ) {
	_f = 0, x = 0;
	while ( _c = getchar (), !isdigit ( _c ) ) if ( _c == '-' ) _f = 1;
	while ( isdigit ( _c ) ) x = x * 10 + _c - '0', _c = getchar (); if ( _f ) { x = -x; }
}

template < class type > inline void chkmin ( type &x, type y ) { x = ( x <= y ? x : y ); }
template < class type > inline void chkmax ( type &x, type y ) { x = ( x >= y ? x : y ); }

const int N = 2e5 + 5;
const int M = 3e6 + 5;

int n, m;
string s[N];

int idx;

struct Node {
	int ch[27], len, fail, val;
} ac[M];

int res[N], p[M], tail;

int C ( char c ) {
	if ( c == '*' ) {
		return 26;
	}
	return c - 'a';
}

void insert ( int id, string s ) {
	int x = 0;
	for ( int i = 0; i < s.size (); i ++ ) {
		if ( !ac[x].ch[C ( s[i] )] ) {
			ac[x].ch[C ( s[i] )] = ++ idx;
		}
		x = ac[x].ch[C ( s[i] )];
		ac[ac[x].ch[C ( s[i] )]].len = ac[x].len + 1;
	}
	res[id] = x;
}

void get_fail () {
  queue < int > q;
  for ( int i = 0; i < 27; i ++ ) {
    if ( ac[0].ch[i] ) {
      ac[ac[0].ch[i]].fail = 0;
      q.push ( ac[0].ch[i] );
    }
  }
  while ( !q.empty () ) {
    int x = q.front ();
    q.pop ();
		p[tail ++] = x;
    for ( int i = 0; i < 27; i ++ ) {
      if ( ac[x].ch[i] ) {
        ac[ac[x].ch[i]].fail = ac[ac[x].fail].ch[i];
        q.push ( ac[x].ch[i] );
      }
      else {
        ac[x].ch[i] = ac[ac[x].fail].ch[i];
      }
    }
  }
}

void query ( string s ) {
	int x = 0, len = s.size ();
	for ( int i = 0; i < s.size (); i ++ ) {
		x = ac[x].ch[C ( s[i] )];
		for ( ; ac[x].len - 1 > len / 2; x = ac[x].fail ) {
			x = x;
		}
		ac[x].val ++;
	}
}

void Solve () {
	cin >> n >> m;
	for ( int i = 1; i <= n; i ++ ) {
		cin >> s[i];
		s[i] = s[i] + "*" + s[i];
	}
	for ( int i = 1; i <= m; i ++ ) {
		string t;
		cin >> t;
		if ( t[0] == '*' ) {
			t = t.substr ( 1 ) + "*";
		}
		else if ( t[t.size () - 1] == '*' ) {
			t = "*" + t.substr ( 0, t.size () - 1 );
		}
		else {
			for ( int j = 0; j < t.size (); j ++ ) {
				if ( t[j] == '*' ) {
					t = t.substr ( j + 1 ) + "*" + t.substr ( 0, j );
					break;
				}
			}
		}
		insert ( i, t );
	}
	get_fail ();
	for ( int i = 1; i <= n; i ++ ) {
		query ( s[i] );
	}
	while ( tail -- ) {
		ac[ac[p[tail]].fail].val += ac[p[tail]].val;
	}
	for ( int i = 1; i <= m; i ++ ) {
		cout << ac[res[i]].val << '\n';
	}
}

signed main () {
#ifdef judge
	freopen ( "Code.in", "r", stdin );
	freopen ( "Code.out", "w", stdout );
	freopen ( "Code.err", "w", stderr );
#endif
	Solve ();
	return 0;
}
2024/4/14 19:42
加载中...