poj 2778 AC 自动机 + 矩阵快速幂

AC自动机构建fail 指针时与 跟 原来匹配时的 AC自动机有改动。。 就是如果    这个节点k没有next[ i ] , 并不是直接跳过 ,而是 由于求转移矩阵的需要 ,顺着 k 的fail 指针 一直找到 有 next[ i ] ,然后把 k点的 next [ i ] 的指针 指向找到的那个 next[ i ] ,这样 就减少了 , 在求转移矩阵的时候, 失配时的跳转。 但这种方式 只适合求转移矩阵,不能用于匹配。。。。。



#include 
#include 
#include 

using namespace std;

// AC 自动机 模版
typedef long long LL;
const int maxK = 4;
const int maxM = 101;
int size = 0 ; // the size of matrix
struct TreeNode
{
	TreeNode *next[maxK];
	TreeNode *fail;
	bool accept;
	int count;
	int id;
	void init(TreeNode *fl, int i)
	{
		accept = false;
		fail = fl;
		id = i;
		count = 0;
		memset(next, 0, sizeof(next));
	}
};

//buildHash()
//init(()
//insert()
//finish()
//match(), buildMat()

template
struct AC
{
	TreeNode *root, *nodes[maxM];
	TreeNode *queue[maxM];
	bool visit[maxM];
	int hash[256];
	int C;
	TreeNode* newNode()
	{
		TreeNode *res = new TreeNode;
		res->init(root, C);
		nodes[C++] = res;
		size = C;
		return res;
	}
	void init()
	{
		C = 0;
		root = NULL;
		root = newNode();
		root -> fail = NULL;
		hash['A'] = 0;
		hash['C'] = 1;
		hash['G'] = 2;
		hash['T'] = 3;
	}
	void insert(char str[])
	{
		TreeNode *current = root;
		for (int i = 0; str[i]; i++)
		{
			if (!current->next[hash[str[i]]])
				current->next[hash[str[i]]] = newNode();
	//		cout << C-1 << " "<next[hash[str[i]]];
		}
		current->accept = true;//be careful of the repetation
		current->count++;
	}
	void finish()//Build Fail
	{
		int head = 0, tail = 0;
		queue[tail++] = root;
		while (head != tail)
		{
			TreeNode *current = queue[head++];
			for (int i = 0; i < maxK; i++)
			{
				if (current->next[i]){
				  queue[tail++] = current->next[i];
				  if (current == root)
					continue;
				  for (TreeNode *t = current->fail; t; t = t->fail)
				  { 
					if (t->next[i])
					{
						current->next[i]->fail = t->next[i];
						current->next[i]->accept |= t->next[i]->accept;
						break;
					}
				  }
				}else{
				  for(TreeNode *t = current->fail;t; t= t->fail){
				      if(t->next[i]){
				         current->next[i] = t->next[i];
					 break;
				      }   
				  }
				}
			}
		}
	}
	void buildMat(T mat[maxM][maxM])//all legal
	{
		for (int i = 0; i < C; i++)
			for (int j = 0; j < C; j++)
				mat[i][j] = 0;
		for (int i = 0; i < C; i++)
		{
			for (int j = 0; j < maxK; j++)
			{
				int flag = 1;
				for (TreeNode *t = nodes[i]; t; t = t->fail)
				{
					if (t->accept)
						break;
					if (t->next[j])
					{
						flag = 0;
						mat[i][t->next[j]->id] += !t->next[j]->accept;
						break;
					}
				}
				mat[i][0] += flag;
			}
		}
	}
        void  buildMat2(T mat[maxM][maxM]){
	   for(int i= 0;iaccept) break;
		    if(t->next[j]){
	//		    if( t -> next[j] -> id== 3 )cout <next[j]->id] += !t->next[j]->accept;
		    }else{
		       mat[i][0] ++;
		    }
	     }
	  }
	}
};
//  矩阵快速幂 模版
 const int  MOD = 100000;
const int maxn = maxM;
struct Mat{
	long long mat[maxn][maxn];
} E,g;
void init_E(){
   for(int i=0;i>=1){
		if(x&1)
			c=c*a;
		a=a*a;
	}
	return c;
}
int m , n ;
char ss[12];
int mat[maxn][maxn];
int main(){
   scanf("%d%d",&m,&n);
   AC ac;
   ac.init();
   while(m--){
      scanf("%s",ss);
      ac.insert(ss);
   }
   ac.finish();
   ac.buildMat2(mat);
   Mat m1;
   init_E();
   for(int  i=0;i= MOD)
	   ans %= MOD;
   cout << ans <



你可能感兴趣的:(POJ,每日一题)