#include <iostream>
#include <vector>
#include <unordered_map>
#include <bitset>

constexpr int64_t p = 998244353;

typedef std::unordered_map<uint64_t, int64_t> flagmap;

bool isflag(int a, int b, int c, int d)
{
    return a == 0 && b == 1 && c ==2 && d == 1;
}

void populateNoFlags(const std::vector<uint64_t> &grid, flagmap *fm, int cur, int m, uint64_t hash)
{
    if(cur == m)
    {
        fm[0][hash] = 1;
        return;
    }

    if(grid[cur] == 3)
    {
        for(uint64_t j=0; j<3; j++)
        {   
            uint64_t newhash = hash;
            newhash |= (j << (2*cur));
            populateNoFlags(grid, fm, cur+1, m, newhash);
        }
    }
    else
    {
        hash |= (grid[cur] << (2*cur));
        populateNoFlags(grid, fm, cur+1, m, hash);
    }
}

int main()
{
    int n, m;
    std::cin >> n >> m;
    std::vector<uint64_t> grid(n*m);
    for(int i=0; i<n*m; i++)
    {
        char c;
        std::cin >> c;
        if(c == 'I')
            grid[i] = 0;
        else if(c == 'C')
            grid[i] = 1;
        else if(c == 'P')
            grid[i] = 2;        
        else
            grid[i] = 3;
    }
    
    flagmap noflags[3];
    flagmap flags[3];
    
    populateNoFlags(grid, noflags, 0, m, 0);
    
    for(int row=1; row<n; row++)
    {
        {
            flagmap newnoflags[3];
            flagmap newflags[3];
            
            for(int prev=0; prev<3; prev++)
            {
                for(auto it : noflags[prev])
                {
                    uint64_t newhash = it.first;
                    newhash &= ~(3ULL);
                    std::vector<uint64_t> toprocess;
                    if(grid[row*m] == 3)
                        toprocess = {0ULL, 1ULL, 2ULL};
                    else toprocess.push_back(grid[row*m]);
                    for(uint64_t j : toprocess)
                    {
                        newnoflags[it.first & 3][newhash | j] = (newnoflags[it.first & 3][newhash | j] + it.second) % p;
                    }
                }
                for(auto it : flags[prev])
                {
                    uint64_t newhash = it.first;
                    newhash &= ~(3ULL);
                    std::vector<uint64_t> toprocess;
                    if(grid[row*m] == 3)
                        toprocess = {0ULL, 1ULL, 2ULL};
                    else toprocess.push_back(grid[row*m]);
                    for(uint64_t j : toprocess)
                    {
                        newflags[it.first & 3][newhash | j] = (newflags[it.first & 3][newhash | j] + it.second) % p;
                    }
                }
            }
            for(int i=0; i<3; i++)
            {
                noflags[i] = newnoflags[i];
                flags[i] = newflags[i];
            }
        }
        for(int col = 1; col < m; col++)
        {
            flagmap newnoflags[3];
            flagmap newflags[3];
            
            for(int prev=0; prev<3; prev++)
            {
                for(auto it : noflags[prev])
                {
                    uint64_t newhash = it.first;
                    newhash &= ~(3ULL << (2*col));
                    std::vector<uint64_t> toprocess;
                    if(grid[row*m + col] == 3)
                        toprocess = {0ULL, 1ULL, 2ULL};
                    else
                        toprocess.push_back(grid[row*m + col]);
                    for(uint64_t j : toprocess)
                    {            
                        if(isflag(prev, (it.first >> (2*col)) & 3ULL, (it.first >> (2*(col-1))) & 3ULL, j))
                            newflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] + it.second) % p;
                        else
                        {
                            newnoflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newnoflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] + it.second) % p;
                        }
                    }
                }
                for(auto it : flags[prev])
                {
                    uint64_t newhash = it.first;
                    newhash &= ~(3ULL << (2*col));
                    std::vector<uint64_t> toprocess;
                    if(grid[row*m + col] == 3)
                        toprocess = {0ULL, 1ULL, 2ULL};
                    else
                        toprocess.push_back(grid[row*m + col]);                        
                    for(uint64_t j : toprocess)
                    {          
                        int idx = (it.first >> (2*col)) & 3ULL;
                        newflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] + it.second) % p;
                    }
                }
            }
            for(int i=0; i<3; i++)
            {
                noflags[i] = newnoflags[i];
                flags[i] = newflags[i];            
            }
        }
    }
    
    uint64_t finalanswer = 0;
    for(int j=0; j<3; j++)
    {
        for(auto it : flags[j])
        {
            finalanswer = (finalanswer + it.second) % p;
        }
    }
    
    std::cout << finalanswer << std::endl;
}
