source_code: import java.util.Optional;
  import java.util.Scanner;
  
  public class Main {
  	public static void main(String[] args) {
  		Main main = new Main();
  		main.solveC();
  	}
  
  	private void solveA() {
  		Scanner sc = new Scanner(System.in);
  		String first = sc.next();
  		String last = sc.next();
  		String answer = first.substring(0, 1) + last.substring(0, 1);
  		for (int i = 2; i <= first.length(); i++) {
  			String current = first.substring(0, i) + last.substring(0, 1);
  			if (answer.compareTo(current) > 0) {
  				answer = current;
  			}
  		}
  		System.out.println(answer);
  	}
  
  	private void solveB() {
  		Scanner sc = new Scanner(System.in);
  		int N = sc.nextInt();
  		int layer = 0;
  		for (int i = 1; i <= N; i++) {
  			int max = N - i + 1;
  			layer += i < max ? i : max;
  		}
  		System.out.println(layer);
  	}
  
  	private void solveC() {
  		Scanner sc = new Scanner(System.in);
  		final long MOD_NUM = 1000000007L;
  		int N = sc.nextInt();
  		long[] level = new long[N + 2];
  		level[0] = 1;
  		sc.nextLine();
  		String pre = "s";
  		for (int i = 0; i < N; i++) {
  			String line = sc.nextLine();
  			long[] next_level = new long[N + 2];
  			if (pre.equals("f")) {
  				for (int j = 1; j < N + 1; j++) {
  					next_level[j] = level[j - 1];
  				}
  			}
  			if (pre.equals("s")) {
  				for (int j = N; j >= 0; j--) {
  					next_level[j] = (next_level[j + 1] + level[j]) % MOD_NUM;
  				}
  			}
  			pre = line;
  			level = next_level;
  		}
  		long answer = 0L;
  		for (int i = 0; i < N + 1; i++) {
  			answer = (answer + level[i]) % MOD_NUM;
  		}
  		System.out.println(answer);
  	}
  
  	private void solveD() {
  		Scanner sc = new Scanner(System.in);
  		int N = sc.nextInt();
  		System.out.println(N);
  	}
  
  	private void solveE() {
  		Scanner sc = new Scanner(System.in);
  		int N = sc.nextInt();
  		System.out.println(N);
  	}
  
  	private void solveF() {
  		Scanner sc = new Scanner(System.in);
  		int N = sc.nextInt();
  		System.out.println(N);
  	}
  
  	interface Graph {
  		void link(int from, int to, long cost);
  		Optional<Long> getCost(int from, int to);
  		int getVertexNum();
  	}
  
  	interface FlowResolver {
  		long maxFlow(int from, int to);
  	}
  
  	/**
  	 * グラフの行列による実装
  	 * 接点数の大きいグラフで使うとMLEで死にそう
  	 */
  	class ArrayGraph implements Graph {
  		private Long[][] costArray;
  		private int vertexNum;
  
  		public ArrayGraph(int n) {
  			costArray = new Long[n][];
  			for (int i = 0; i < n; i++) {
  				costArray[i] = new Long[n];
  			}
  			vertexNum = n;
  		}
  
  		@Override
  		public void link(int from, int to, long cost) {
  			costArray[from][to] = new Long(cost);
  		}
  
  		@Override
  		public Optional<Long> getCost(int from, int to) {
  			return Optional.ofNullable(costArray[from][to]);
  		}
  
  		@Override
  		public int getVertexNum() {
  			return vertexNum;
  		}
  	}
  
  	/**
  	 * DFS(深さ優先探索)による実装
  	 * 計算量はO(E*MaxFlow)のはず (E:辺の数, MaxFlow:最大フロー)
  	 */
  	class DfsFlowResolver implements FlowResolver {
  		private Graph graph;
  		public DfsFlowResolver(Graph graph) {
  			this.graph = graph;
  		}
  
  		/**
  		 * 最大フロー(最小カット)を求める
  		 * @param from 始点(source)のID
  		 * @param to 終点(target)のID
  		 * @return 最大フロー(最小カット)
  		 */
  		public long maxFlow(int from, int to) {
  			long sum = 0L;
  			long currentFlow;
  			do {
  				currentFlow = flow(from, to, Long.MAX_VALUE / 3, new boolean[graph.getVertexNum()]);
  				sum += currentFlow;
  			} while (currentFlow > 0);
  			return sum;
  		}
  
  		/**
  		 * フローの実行 グラフの更新も行う
  		 * @param from 現在いる節点のID
  		 * @param to 終点(target)のID
  		 * @param current_flow ここまでの流量
  		 * @param passed 既に通った節点か否かを格納した配列
  		 * @return 終点(target)に流した流量/戻りのグラフの流量
  		 */
  		private long flow(int from, int to, long current_flow, boolean[] passed) {
  			passed[from] = true;
  			if (from == to) {
  				return current_flow;
  			}
  			for (int id = 0; id < graph.getVertexNum(); id++) {
  				if (passed[id]) {
  					continue;
  				}
  				Optional<Long> cost = graph.getCost(from, id);
  				if (cost.orElse(0L) > 0) {
  					long nextFlow = current_flow < cost.get() ? current_flow : cost.get();
  					long returnFlow = flow(id, to, nextFlow, passed);
  					if (returnFlow > 0) {
  						graph.link(from, id, cost.get() - returnFlow);
  						graph.link(id, from, graph.getCost(id, from).orElse(0L) + returnFlow);
  						return returnFlow;
  					}
  				}
  			}
  			return 0L;
  		}
  	}
  
  	/**
  	 * 1-indexedのBIT配列
  	 */
  	class BinaryIndexedTree {
  		private long[] array;
  
  		public BinaryIndexedTree(int size) {
  			this.array = new long[size + 1];
  		}
  
  		/**
  		 * 指定した要素に値を加算する
  		 * 計算量はO(logN)
  		 * @param index 加算する要素の添字
  		 * @param value 加算する量
  		 */
  		public void add(int index, long value) {
  			for (int i = index; i < array.length; i += (i & -i)) {
  				array[i] += value;
  			}
  		}
  
  		/**
  		 * 1〜指定した要素までの和を取得する
  		 * 計算量はO(logN)
  		 * @param index 和の終端
  		 * @return 1〜indexまでの和
  		 */
  		public long getSum(int index) {
  			long sum = 0L;
  			for (int i = index; i > 0; i -= (i & -i)) {
  				sum += array[i];
  			}
  			return sum;
  		}
  	}
  }